1.多线程数据共享,资源保护方法:
1)mutex
如果获取不到锁,让出CPU,将线程加入等待队列。
任务耗时比上下文切换要长
2)spinlock
如果获取不到锁,则继续死循环检查锁的状态,如果是lock状态,则继续死循环,否则上锁,结束死循环。
(1)任务不能存在阻塞 (2)任务耗时短,几条指令
3)无锁CAS(Compare and Swap)
比较并交换,是一种原子操作
bool CAS( int * pAddr, int nExpected, int nNew )
atomically {
if ( *pAddr == nExpected ) {
*pAddr = nNew ;
return true ;
} else
return false ;
}
2.操作的原子性
#include <stdio.h>
int i = 0;
// gcc -S 1_test_i++.c
int main(int argc, char **argv)
{
++i;
return 0;
}
++i 不是原子操作
汇编代码
movl i(%rip), %eax //把i从内存加载到寄存器
addl $1, %eax //把寄存器的值加1
movl %eax, i(%rip) //把寄存器的值写回内存
static int lxx_atomic_add(int *ptr, int increment)
{
int old_value = *ptr;
__asm__ volatile("lock; xadd %0, %1 \n\t"
: "=r"(old_value), "=m"(*ptr)
: "0"(increment), "m"(*ptr)
: "cc", "memory");
return *ptr;
}
3.原子操作
gcc、g++编译器提供了一组原子操作api
bool __sync_bool_compare_and_swap (type *ptr, type oldval type newval, ...)
C++11也提供了一组api,定义在<atomic>中
X86架构原子操作实现
static int lxx_atomic_add(int *ptr, int increment)
{
int old_value = *ptr;
__asm__ volatile("lock; xadd %0, %1 \n\t"
: "=r"(old_value), "=m"(*ptr)
: "0"(increment), "m"(*ptr)
: "cc", "memory");
return *ptr;
}
4.无锁队列的实现
无锁队列适用于队列push、pop非常频繁的场景,效率要比mutex高很多