技术介绍:
cas 原子操作:是有cpu提供的原子操作。
<pre name="code" class="cpp">MyDeque
{
Node *head;
Node *tail;
void enQueue(T value);
T deQueue();
}
入队操作
void enQueue(T value)
{
node * q=getNewNode();
q->next=null;
q->value=T;
// 通过原子操作把q加入到队列
while(1)
{
node *tem=tail;
while(tem->next!=null) //防止其他线程已经把元素加入队列,但是没有更新tail
tem=tem->next;
if( CAS(&tail->next,null,q))
break;
}
//通过援助操作,更新tail
CAS(&tail,tail,tail->next);
}
出对操作
T deQueue()
{
while(1)
{
node *q=head;
if(q->next==null)//没有元素,带头结点的队列
return null;
if(CAS( &head ,q,head->next)) 更新head
break;
}
T temValue=q->value;
recycle(q); //回收空间
return temValue;
}
以上是队列出对入队操作,
Pseudocode from article of the above name in PODC96 (with two typos corrected), by Maged M. Michael and Michael L. Scott
关于该算法的一些优化
1.该算法的入队时候需要重新分配空间,分配空间这个开销是很大的,实际上可以不用每次入队都分配工具,可以是实现个多线程安全的freeList,用来存放可用的空间结点,每次入队了,从freeList得到一个空间,加入队列。出队时,可是把该空间加入到freeList,这样可以节省空间分配和回收的开销,同时也可以避免ABA问题。这个方法可以参考lmax disruptor.
2.关于伪共享的问题,需要cache line填充。在head,tail之间可以填充64字节的无关数据。