diff --git a/a-java-fork-join-framework/README.md b/a-java-fork-join-framework/README.md index be59b03..45f9b97 100644 --- a/a-java-fork-join-framework/README.md +++ b/a-java-fork-join-framework/README.md @@ -212,7 +212,7 @@ if (++base < top) ... 在上述每种情况下他们都通过比较两个索引来检查这样是否会导致`deque`变成一个空队列。一个不对称的规则将用于防止潜在的冲突:`pop`会重新检查状态并在获取锁之后继续(对`take`所持有的也一样),直到队列真的为空才退出。而`take`操作会立即退出,特别是当尝试去获得另外一个任务。与其他类似使用`Clik`的`THE`协议一样,这种不对称性是唯一重要的改变。 -使用`volatile`变量索引`push`操作在队列没有满的情况下不需要同步就可以进行。如果队列将要溢出,那么它首先必须要获得队列锁来重新设置队列的长度。其他情况下,只要确保`top`操作排在队列数组槽盛在抑制干涉带之后更新。 +使用 **_`volatile`_** 变量的索引也使得`push`操作无需同步,除非`deque`数组将要溢出的情况。对于这种溢出情况,必须先获得队列锁来重新设置队列的长度。而对于非溢出情况,只要简单地保证:`top`的更新只发生`deque`数组槽的填充之后,就可以规避`take`操作带来的干扰影响。 在随后的初始化实现中,发现有好几种`JVM`并不符合`Java`内存模型中正确读取写入的`volatile`变量的规则。作为一个工作区,`pop`操作在持有锁的情况下重试的条件已经被调整为:如果有两个或者更少的元素,并且`take`操作加了第二把锁以确保内存屏障效果,那么重试就会被触发。只要最多只有一个索引被拥有者线程丢失这就是满足的,并且只会引起轻微的性能损耗。