同步辅助类Exchanger

Exchanger提供的是一个交换服务,允许原子性的交换两个(多个)对象,但同时只有一对才会成功。JDK 8中直接基于Unsafe实现线程同步。

  1. 类提供对外的操作是同步的;
  2. 用于成对出现的线程之间交换数据;
  3. 可以视作双向的SynchronousQueue;
  4. 可应用于基因算法、管道设计等场景。

在上面的模型中,我们假定一个空的栈(Stack),栈顶(Top)当然是没有元素的。同时我们假定一个数据结构Node,包含一个要交换的元素E和一个要填充的“洞”Node。这时线程T1携带节点node1进入栈(cas_push),当然这是CAS操作,这样栈顶就不为空了。线程T2携带节点node2进入栈,发现栈里面已经有元素了node1,同时发现node1的hold(Node)为空,于是将自己(node2)填充到node1的hold中(cas_fill)。然后将元素node1从栈中弹出(cas_take)。这样线程T1就得到了node1.hold.item也就是node2的元素e2,线程T2就得到了node1.item也就是e1,从而达到了交换的目的。

JDK 5就是采用类似的思想实现的Exchanger。JDK 6以后为了支持多线程多对象同时Exchanger了就进行了改造(为了支持更好的并发),采用ConcurrentHashMap的思想,将Stack分割成很多的片段(或者说插槽Slot),线程Id(Thread.getId())hash相同的落在同一个Slot上,这样在默认32个Slot上就有很好的吞吐量。当然会根据机器CPU内核的数量有一定的优化

适合场景

  1. 可以在线程间传递数据结构,来重复利用它们,减少GC。
  2. ss

在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 CyclicBarrier很有用(CyclicBarriers are useful in programs involving a fixed sized party of threads that must occasionally wait for each other)

References

  1. Java Thread&Concurrency(4): 深入理解Exchanger实现原理

results matching ""

    No results matching ""