AbstractQueuedSynchronizer
的Node
内部类中,对volatile Node prev
成员变量获取方法predecessor()
如下
final Node predecessor() throws NullPointerException {
Node p = prev;
if (p == null)
throw new NullPointerException();
else
return p;
}
在源码中,这里对volatile
类型的成员变量prev
的返回,是先把他赋值给一个中间变量p,然后拿p返回。
这种设计在AQS
的源码中很多地方都有涉及到,包括在其它源码中也经常看到对volatile
类型的变量先赋值给另外一个变量,然后把这个变量返回.
这样设计的目的是什么?
-------Wikipédia
Dans cette méthode
predecessor()
, l'effet deNode p
n'est pas si évident. S'il vous plaît, permettez-moi de rendre l'exemple un peu plus extrême :En supposant que 100 appels de threads changeront la valeur de prev, alors entre #L1 et #L4, toute modification apportée à la variable partagée -- prev sera visible par extremePredecessor().
Cela posera les problèmes suivants :
est très similaire à un verrou de synchronisation. Les mises à jour synchrones de
prev
entraîneront des pertes de performances. Prev deviendra un goulot d'étranglement pour l'ensemble de la file d'attente.La valeur de prev entre #L1 et #L4 peut être incohérente car d'autres threads l'ont modifiée. Cela rend beaucoup plus difficile la compréhension du code.
Si vous utilisez
Node p = prev;
, alors après #L0, il n'est pas nécessaire de synchroniser la valeur dep
.p
de #L1 à #L4 sont également cohérents.Pour
volatile
, voir :Mot clé volatile Java Language Spec
https://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls- 8.3 .1.4