Maison  >  Article  >  Java  >  Comment utiliser la classe d'outil de synchronisation multithread Java CyclicBarrier

Comment utiliser la classe d'outil de synchronisation multithread Java CyclicBarrier

王林
王林avant
2023-05-13 11:19:051200parcourir

    Qu'est-ce que CyclicBarrier

    CyclicBarrier est une classe d'outil de synchronisation fournie dans le package de concurrence Java. Elle permet à plusieurs threads d'attendre à une certaine barrière jusqu'à ce que tous les threads atteignent la barrière avant de poursuivre l'exécution. Le principe d'implémentation de CyclicBarrier est basé sur ReentrantLock et Condition, et l'attente et le réveil des threads sont réalisés en appelant plusieurs fois la méthode wait().

    Utilisation de base de CyclicBarrier

    L'utilisation de base de CyclicBarrier est très simple. Il vous suffit de créer un objet CyclicBarrier et de définir la valeur du compteur sur le nombre de threads en attente. Une fois l'exécution de chaque thread terminée, appelez la méthode wait() de CyclicBarrier pour attendre que les autres threads terminent leur exécution. Lorsque tous les threads atteignent la barrière, la barrière sera ouverte et tous les threads continueront à s'exécuter.

    Implémentation du code source de CyclicBarrier

    Le principe d'implémentation de CyclicBarrier est basé sur ReentrantLock et Condition, et l'attente et le réveil des threads sont obtenus en appelant plusieurs fois la méthode wait(). L'implémentation du code source de CyclicBarrier comprend principalement deux parties : l'initialisation de la barrière et l'attente et le réveil de la barrière.

    (1) Initialisation de CyclicBarrier

    Lors de la création d'un objet CyclicBarrier, vous devez spécifier le nombre de threads en attente et l'opération d'exécution de la barrière. La méthode de construction de l'objet CyclicBarrier est la suivante :

    public CyclicBarrier(int parties, Runnable barrierAction)

    où parties représente le nombre de threads en attente, et barrièreAction représente l'opération effectuée par la barrière.

    Dans la méthode de construction, un tableau ReentrantLock de la taille d'un groupe et un objet Condition seront créés en fonction du nombre de threads en attente. Le tableau ReentrantLock est utilisé pour garantir que plusieurs threads peuvent atteindre la barrière et attendre en même temps, et l'objet Condition est utilisé pour attendre et réveiller les threads.

    (2) Attente et réveil de CyclicBarrier

    Lorsque le thread exécute la méthode wait(), il tentera d'abord d'acquérir le verrou de l'objet ReentrantLock. Si l'acquisition échoue, le thread sera ajouté à la file d'attente. attendre que le verrou soit libéré. Après avoir acquis le verrou, le thread déterminera si le compteur actuel a atteint le nombre de threads en attente. Si tel est le cas, il effectuera des opérations de barrière et réinitialisera le compteur aux parties, réveillant ainsi tous les threads de la file d'attente. Si le compteur n'atteint pas le nombre de threads en attente, le thread sera ajouté à la file d'attente pour attendre l'arrivée des autres threads.

    Le code source de la méthode wait() de CyclicBarrier est le suivant :

    public int await() throws InterruptedException, BrokenBarrierException {
        try {
            // 获取锁
            lock.lock();
            // 计数器减1
            int index = --count;
            if (index == 0) {
                // 如果计数器为0,执行屏障操作并唤醒等待队列中的所有线程
                final Runnable command = barrierCommand;
                if (command != null) {
                    command.run();
                }
                next
            trip.signalAll();
        } else {
            try {
                // 等待其他线程到达屏障处
                int phase = generation;
                trip.await();
                // 如果是最后一个到达屏障的线程,执行屏障操作并唤醒等待队列中的所有线程
                if (phase == generation) {
                    command = barrierCommand;
                    if (command != null) {
                        command.run();
                    }
                }
                // 计数器重置
                nextGeneration();
            } catch (InterruptedException ie) {
                // 如果线程在等待时被中断,抛出InterruptedException异常
                cancel();
                throw ie;
            } catch (BrokenBarrierException bbe) {
                // 如果屏障被破坏,抛出BrokenBarrierException异常
                broken = true;
                trip = new Condition[parties];
                throw bbe;
            }
        }
        return index;
    } finally {
        // 释放锁
        lock.unlock();
    }
    }

    Dans la méthode wait() de CyclicBarrier, acquérez d'abord le verrou de l'objet ReentrantLock et décrémentez le compteur de 1. Si le compteur est à 0, effectuez l'opération de barrière et réveillez tous les threads de la file d'attente. Si le compteur n'est pas à 0, attendez que d'autres threads arrivent à la barrière.

    Pendant le processus d'attente, si le thread est interrompu, une InterruptedException sera levée. Si la barrière est brisée, une BrokenBarrierException sera levée. Si c'est le dernier thread à atteindre la barrière, l'opération de barrière sera effectuée et tous les threads de la file d'attente seront réveillés et le compteur sera réinitialisé aux parties.

    Scénarios d'utilisation de CyclicBarrier

    CyclicBarrier convient aux scénarios dans lesquels plusieurs threads doivent s'attendre les uns les autres pour atteindre un certain point de barrière avant de continuer à s'exécuter. Par exemple, si plusieurs threads doivent exécuter une certaine tâche en même temps, mais qu'une certaine tâche doit attendre que d'autres tâches soient terminées avant de continuer, vous pouvez utiliser CyclicBarrier pour réaliser la synchronisation et la collaboration des threads.

    De plus, CyclicBarrier peut également être utilisé pour mettre en œuvre le traitement du pipeline. Par exemple, dans le modèle producteur-consommateur, plusieurs producteurs peuvent ajouter des données à la file d'attente en même temps. Lorsque la file d'attente est pleine, tous les producteurs doivent attendre. au consommateur de traiter les données. Continuez ensuite à ajouter des données.

    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!

    Déclaration:
    Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer