SynchronousQueue添加元素跟获取元素都是调用Transfer的transfer方法,传递的元素e为null时代表着获取,传递的元素e非空时代表着添加。
SynchronousQueue的公平与非公平模式,其实就是Transfer的实现类不同,公平是TransferQueue,等待链表是队列。非公平是TransferStack,等待链表是栈。以下以TransferQueue为例。
transfer方法中,
若队列为空(仅有傀儡节点)或者当前的请求与队列中节点的模式相同(一样是取或者一样是放),那就构造等待节点,等待节点中存放了元素,当前线程。通过cas将队尾元素的next指针指向新节点,再通过cas将队尾tail指针指向新节点。进入自旋等待,先是cpu自旋,并通过Thread.onSpinWait()告知cpu当前线程处于自旋中,可分配更多资源给其他线程。自旋期间结果未出(当节点中元素与原元素不同时,说明结果已出),那便调用LockSupport.park阻塞线程。
若当前的请求与队列中节点的模式不同,那便将第一个实际节点(傀儡头节点的next)的元素cas替换成当前请求的元素,再将头节点指针cas指向该节点。通过LockSupport.unpark唤醒节点的线程。
总结一下,就是当链表为空或者链表中节点跟请求是同模式时,构造等待节点通过cas方式加入链表,并自旋等待或阻塞等待。当链表中节点跟请求非同模式时,便cas从链表中取出一个节点,替换它的元素并唤醒它的线程。