CAS无锁队列与线程同步
Posted will287248100
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CAS无锁队列与线程同步相关的知识,希望对你有一定的参考价值。
线程同步
同步:同步控制着线程之间的执行顺序,不让他们抢占式执行。在保证数据安全的前提下,让线程能够按照某种特定的顺序访问临界资源,从而有效避免饥饿问题,叫做同步。
原子访问:同一时刻,只允许一个线程访问临界资源;
原子操作:指多步操作组成的一个操作;原子操作中线程不会被切换,线程切换要么在原子操作之前,要么在原子操作完成之后。
在单核系统里,单个的机器指令可以看成是原子操作(如果有编译器优化、乱序执行等情况除外);在多核系统中,单个的机器指令就不是原子操作,因为多核系统里是多指令流并行运行的,一个核在执行一个指令时,其他核同时执行的指令有可能操作同一块内存区域,从而出现数据竞争现象。多核系统中的原子操作通常使用内存栅障(memory barrier)来实现,即一个CPU核在执行原子操作时,其他CPU核必须停止对内存操作或者不对指定的内存进行操作,这样才能避免数据竞争问题。
CAS无锁队列:
避免队列放入和读取过于频繁。volatile 修饰变量+type __sync_val_compare_and_swap (type *ptr, type oldval type newval)
CAS原理:compare and swap;比较内存有没有被修改,期望值和读出来的值是否一致
应用:无锁队列,ZMQ中的设计用到了cas无锁队列; disruptor库。会涉及到cache的操作的问题:每个CPU都有独立的cache, 当cache修改了,cache1和cache2会失效的问题;
缺点:出了问题很难debug;考验设计能力;
mutex互斥锁:如果获取不到锁,线程就会进入休眠,让出CPU资源,线程加入到所等待队列中;
缺点:切换上下文引起的效率的问题;要避免频繁的切换上下文成为应用场景的选择;
临界区执行代码比较长时mutex和spinlock相比较会占优势一点;比如:for(i =0 ;i <10000;i++){sum++;}
spinlock自旋锁:
特点:忙等待,继续去检测锁的状态;
应用场景中:1.临界区内不能存在阻塞;2,临界区代码段执行时间不能过长,比如:i++;++i......;
++i;i++;
- 把i从内存加载到寄存器;
- 执行操作;
- 写回内存;
gcc -S Filenale.c
Vim Filenam.s
其反汇编代码:
movl i(%rip), %eax
addl $1, %eax
movl %eax, i(%rip)
原子操作指令API:add,sub,or,and,xor,nand
X86内存汇编指令加操作:lxx_atomic_add(&s_i, 1);
static int lxx_atomic_add(int *ptr, int increment)
{
int old_value = *ptr;
__asm__ volatile("lock; xadd %0, %1 "
: "=r"(old_value), "=m"(*ptr)
: "0"(increment), "m"(*ptr)
: "cc", "memory");
return *ptr;
}
以上是关于CAS无锁队列与线程同步的主要内容,如果未能解决你的问题,请参考以下文章
非阻塞同步算法与CAS(Compare and Swap)无锁算法