看 LinkedBlockingQueue 的源码,阻塞型的生产消费模式,用了两把锁,其实用一把锁也能搞定!但是两把锁的好处是,提高了并发读、写效率,读和写可并发执行,过程技术关键点在:队列为null时的临界情况处理。这时候是如何保证并发读、写的线程安全的。
节点操作保证安全性
平移Header节点,移除头结点法 无线程安全,因为Header平移到下一个节点(可能就是Tail节点),然后移除上个节点,并把当前节点的数值除去返回。
保持Header节点不动,移除中间节点法 有线程安全,因为Header 所在链条存在丢失Tail的风险。比如多线程时,先执行dequeue 在执行 enqueue。
public boolean offer(E e, long timeout, TimeUnit unit){ 插入节点
public boolean offer(E e) { 插入节点
public E take() throws InterruptedException { 移除节点
public E poll(long timeout, TimeUnit unit) throws InterruptedException { 移除节点
/**
* Links node at end of queue.
*
* @param node the node
*/
private void enqueue(Node<E> node) {
last = last.next = node;
}
/**
* Removes a node from head of queue.
*
* @return the node
*/
private E dequeue() {
Node<E> h = head;
Node<E> first = h.next;
h.next = h; // help GC
head = first;
E x = first.item;
first.item = null;
return x;
}
//有线程安全
private E dequeue() {
Node first = head.next;
head.next= head.next.next;
first.next = null;
return first;
}