java - Vous recherchez une explication sur un morceau de code source dans ArrayBlockingQueue
阿神
阿神 2017-05-27 17:41:19
0
2
876

Pourquoi la méthode take() utilise-t-elle une boucle while au lieu de if pour juger si le nombre d'éléments dans la file d'attente est 0

?

我认为,如果notEmpty.await()方法既然苏醒返回了 ,那么此线程肯定拿到了lock。

La raison du réveil est également parce que la méthode put() insère de nouveaux éléments et que les autres threads ne peuvent pas obtenir le verrou, donc naturellement ils ne peuvent pas supprimer les éléments. Donc, à ce moment, pour le thread qui a obtenu le verrou, le. count n'est certainement pas 0. N'hésitez pas à exécuter dequeue() pour obtenir des éléments.
Je ne sais pas ce que l'auteur veut dire par utiliser while ?

阿神
阿神

闭关修行中......

répondre à tous(2)
漂亮男人

"Puisque la méthode notEmpty.await() se réveille et revient, alors ce thread doit avoir obtenu le verrou" Cette phrase est correcte.

Supposons que le code que vous écrivez soit :

if (count == 0)
    notEmpty.await();

Une chose qui est claire est que nous devons nous assurer qu'une condition qui doit être remplie avant return dequeue() est count != 0. Nous supposons que le thread A a obtenu return dequeue() 之前需要满足的一个条件是 count != 0。我们假设 线程A 此时拿到了 lock,那么 线程A 的 notEmpty.await() 此时便会停止阻塞,准备向下执行 return dequeue()。但是假设在竞争激烈的条件下,线程A 拿到 lock 之后,准备执行下一条 JVM 指令的时候,线程B 此时抢占了 lock,然后继续向下执行 return dequeue(),刚好使得 count 变为了 0;而此时因为写的只是 if(count == 0),那么线程 A 在拿到 lock 之后,还是会继续向下执行 return dequeue(),从而导致了错误。

关于为什么wait()await()lock à ce moment-là, alors le notEmpty.await() du thread A cessera de se bloquer à ce moment et se préparera à exécuter return dequeue() . Mais en supposant que dans des conditions de concurrence féroce, une fois que le thread A a obtenu le verrou, lors de la préparation de l'exécution de l'instruction JVM suivante, le thread B saisit le verrou à ce moment-là, puis continue d'exécuter return dequeue(), Cela fait simplement que count devient 0 ; et comme ce qui est écrit à ce moment n'est que if(count == 0), alors le thread A continuera à exécuter return dequeue(( ), provoquant l'erreur. Pour savoir pourquoi wait() et await() sont des méthodes qui bloquent lorsque les conditions ne sont pas rempliesdoivent être utilisées dans une boucle while, vous pouvez vous référer à "

Java efficace 🎜》Deuxième édition Article 69 (page 244). 🎜
黄舟
public ArrayBlockingQueue(int capacity, boolean fair) {
    if (capacity <= 0)
        throw new IllegalArgumentException();
    this.items = new Object[capacity];
    lock = new ReentrantLock(fair);
    notEmpty = lock.newCondition();    //notEmpty 就是这个锁的条件
    notFull =  lock.newCondition();
}

Ainsi, lorsque la file d'attente actuelle dans votre code est vide (count == 0), l'appel notEmpty.await(),这段代码对锁是有影响的,实际上底层上已经释放了锁,只是这个方法保证了被唤醒时一定又能够拿回锁(当有元素放入队列会调用notEmpty.signal()进行唤醒),那为什么需要使用while呢?因为insert后lock.unlock,未必notEmpty.await() vous réveillera immédiatement. Vous pouvez insérer un fil de discussion pour exécuter la méthode Remove avant

.
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal