Maison > Java > javaDidacticiel > Comment implémenter la sécurité des threads dans la programmation simultanée Java

Comment implémenter la sécurité des threads dans la programmation simultanée Java

WBOY
Libérer: 2023-05-21 15:14:13
avant
1525 Les gens l'ont consulté

    1. Qu'est-ce que la sécurité des threads

    Lorsque plusieurs threads accèdent à une classe, quelle que soit la méthode d'appel utilisée par l'environnement d'exécution ou la manière dont ces threads s'exécuteront alternativement, et rien n'est nécessaire dans le code d'appel principal. cette classe peut présenter un comportement correct malgré une synchronisation ou une coordination supplémentaire, alors cette classe est dite thread-safe.

    Les objets sans état doivent être thread-safe, tels que : Servlet. Servlet

    2.原子性

    2.1 竞争条件

    由于不恰当的执行时序而出现不正确的结果的情况,就是竞争条件。

    “先检查后执行”操作,即通过一个可能实效的观测结果来决定下一步的动作。比如:延迟初始化。

    if(instance == null) {
        instance = new SomeObject();
    }
    Copier après la connexion

    “读取-修改-写入”的操作,其结果状态依赖于之前的状态。如:递增运算。

    long count = 0;
    count++;
    Copier après la connexion

    2.2 复合操作

    原子操作是指,对于访问同一个状态的所有操作(包括此操作本身)来说,这个操作是以一个原子方式执行(不可分割)的操作。

    为了确保线程安全性,包含了一组必须以原子方式执行的操作,称为复合操作。

    递增运算可以使用一个现有的线程安全类,确保线程安全性。如:

    AtomicLong count = new AtomicLong(0);
    count.incrementAndGet();
    Copier après la connexion

    3.加锁机制

    如果一个类只有一个状态变量,可以通过使用线程安全的状态变量来确保类的线程安全性。当一个类有更多的状态时,仅仅添加更多的线程安全状态变量是不够的。为了确保状态的一致性,必须在单个原子操作中更新所有相关的状态变量。

    3.1 内置锁

    Java提供一种内置锁:同步代码块,它包括:一个作为锁的对象引用、一个作为由这个锁保护的代码块。

    以关键字synchronized来修饰的方法就是一种横跨整个方法体的同步代码块,其中该同步代码块的锁就是方法调用所在的对象。静态的synchronized

    2. Atomicité

    2.1 Condition de concurrence

    Une condition de concurrence se produit lorsque des résultats incorrects se produisent en raison d'un timing d'exécution incorrect.

    L'opération « vérifier d'abord puis exécuter » consiste à déterminer la prochaine action en fonction d'un résultat d'observation possible et efficace. Par exemple : initialisation paresseuse.

    public class Widget {
        public synchronized void doSomething() {
            //......
        }
    }
    public class LoggingWidget extends Widget {
        public synchronized void doSomething() {
            //......
            super.doSomething();//假如没有可重入的锁,该语句将产生死锁。
        }
    }
    Copier après la connexion

    Opération "Lecture-Modification-Ecriture", l'état du résultat dépend de l'état précédent. Tels que : opération d’incrémentation.

    @ThreadSafe
    public class SynchronizedFactorizer implements Servlet {
        @GuardedBy("this") private BigInteger lastNumber;
        @GuardedBy("this") private BigInteger[] lastFactors;
    
        public synchronized void service(ServletRequest req,
                                         ServletResponse resp) {
            BigInteger i = extractFromRequest(req);
            if (i.equals(lastNumber))
                encodeIntoResponse(resp, lastFactors);
            else {
                BigInteger[] factors = factor(i);//因数分解计算
                lastNumber = i;
                lastFactors = factors;//存放上一次计算结果
                encodeIntoResponse(resp, factors);
            }
        }
    }
    Copier après la connexion

    2.2 Opération composite

    L'opération atomique signifie que pour toutes les opérations qui accèdent au même état (y compris l'opération elle-même), cette opération est effectuée de manière atomique (indivisible).

    Pour garantir la sécurité des threads, un ensemble d'opérations qui doivent être effectuées de manière atomique est inclus, appelées opérations composites.

    Les opérations incrémentielles peuvent utiliser une classe thread-safe existante pour garantir la sécurité des threads. Tels que :

    public class CachedFactorizer implements Servlet {
        @GuardedBy("this") private BigInteger lastNumber;
        @GuardedBy("this") private BigInteger[] lastFactors;
    
        public void service(ServletRequest req, ServletResponse resp) {
            BigInteger i = extractFromRequest(req); 
            BigInteger[] factors = null;      
            synchronized (this) {
                if (i.equals(lastNumber)) {
                   factors = lastFactors.clone();
                }         
            }    
            if (factors == null) {        
                factors = factor(i);
                synchronized (this) {
                   lastNumber = i;
                   lastFactors = factors.clone();
                }
            }
            encodeIntoResponse(resp, factors);
        }
    }
    Copier après la connexion
    3. Mécanisme de verrouillage🎜🎜Si une classe n'a qu'une seule variable d'état, vous pouvez garantir la sécurité des threads de la classe en utilisant des variables d'état thread-safe. Lorsqu'une classe a plus d'état, il ne suffit pas d'ajouter davantage de variables d'état thread-safe. Pour garantir la cohérence de l'état, toutes les variables d'état pertinentes doivent être mises à jour en une seule opération atomique. 🎜🎜3.1 Verrou intégré🎜🎜Java fournit un verrou intégré : Bloc de code synchronisé, il comprend : Une référence d'objet comme verrou et une comme code protégé par cette pièce de serrure. 🎜🎜La méthode modifiée avec le mot-clé synchronized est un bloc de code synchronisé qui couvre tout le corps de la méthode, et le verrou du bloc de code synchronisé est l'objet où la méthode est appelée. La méthode statique synchronisée utilise l'objet Class comme verrou. 🎜🎜Lorsqu'un thread entre dans un bloc de code synchronisé, il acquiert automatiquement le verrou ; et lorsque le thread sort du bloc de code synchronisé, il libère automatiquement le verrou ; Au plus un thread peut détenir ce verrou, le code synchronisé est donc exécuté de manière atomique. 🎜🎜3.2 Réentrée🎜🎜Le verrou intégré est réentrant, ce qui signifie que la granularité de l'opération pour acquérir le verrou est le thread, pas l'appel. Lorsqu'un thread tente de réacquérir un verrou qu'il détient déjà, la requête réussit également. 🎜🎜La réentrée améliore encore l'encapsulation du comportement de verrouillage et simplifie le développement de code concurrent orienté objet. 🎜rrreee🎜4. Protéger l'état avec un verrou🎜🎜Pour une variable d'état variable accessible par plusieurs threads en même temps, vous devez maintenir le même verrou lors de l'accès. Dans ce cas, la variable d'état est dite. être contrôlé par ce verrou protégé. 🎜🎜5. Vivacité et performances🎜🎜L'utilisation à gros grain des verrous garantit la sécurité des threads, mais elle peut entraîner des problèmes de performances et de vivacité, tels que : 🎜rrreee🎜Vous pouvez vous assurer que le servlet est cohérent en réduisant la coiffure du bloc de code de synchronisation, tout en maintenant la sécurité des threads. Ne divisez pas ce qui devrait être des opérations atomiques en plusieurs blocs de code synchronisés. Essayez de séparer les opérations qui n'affectent pas l'état partagé et qui prennent beaucoup de temps à s'exécuter à partir du code synchronisé. Tel que : 🎜rrreee

    Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

    Étiquettes associées:
    source:yisu.com
    Déclaration de ce site Web
    Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
    Tutoriels populaires
    Plus>
    Derniers téléchargements
    Plus>
    effets Web
    Code source du site Web
    Matériel du site Web
    Modèle frontal