前言
在JUC包中,除了一些常用的或者说常见的并发工具类(ReentrantLock,CountDownLatch,CyclicBarrier,Semaphore)等,还有一个不常用的线程同步器类 —— Exchanger。
Exchanger是适用在两个线程之间数据交换的并发工具类,它的作用是找到一个同步点,当两个线程都执行到了同步点(exchange方法)之后(有一个没有执行到就一直等待,也可以设置等待超时时间),就将自身线程的数据与对方交换。
Exchanger类结构
如上图UNML,Exchanger类中有两个内部类,一个Node,一个Participant。
Participant继承了ThreadLocal并且重写了其initialValue方法,返回一个Node对象。
1 | /** The corresponding thread local class */ |
Node类封装了两个线程存储的数据对象:
1 | /** |
Exchanger源码分析
1 | "unchecked") ( |
exchange
方法的步骤:
- 如果执行slotExchange有结果就执行后面的arenaExchange
- 如果solt被占用,就执行arenaExchange
- 返回的数据v是对方线程的数据项
- 总结即:如果A线程先调用,那么A的数据项存储的item中
- 则B线程的数据项存储在match中
- 当没有多线程并发操作 Exchange 的时候,使用 slotExchange 就足够了。 slot 是一个 node 对象。
- 当出现并发了,一个 slot 就不够了,就需要使用一个 node 数组 arena 操作了。
Exchanger的使用
下面的例子模拟一个队列中数据的交换使用的场景:
- 线程A往队列中存入数据
- 线程B从队列中消耗数据
- 当线程A存满的时候
- 才交换给线程B
- 当线程B消耗完成之后才交换给线程A。
- 线程A、B的生产和消耗的速率有可能不同
- 对方线程调用exchange之前,另一个线程执行到exchange会阻塞
1 | /** 在对方线程调用exchange之前,另一个线程执行到exchange会阻塞 直到双方都调用exchange */ |