1.多線程數(shù)據(jù)共享,資源保護方法:
1)mutex
如果獲取不到鎖,讓出CPU,將線程加入等待隊列。
任務(wù)耗時比上下文切換要長
2)spinlock
如果獲取不到鎖,則繼續(xù)死循環(huán)檢查鎖的狀態(tài),如果是lock狀態(tài),則繼續(xù)死循環(huán),否則上鎖,結(jié)束死循環(huán)。
(1)任務(wù)不能存在阻塞 (2)任務(wù)耗時短,幾條指令
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從內(nèi)存加載到寄存器
addl $1, %eax //把寄存器的值加1
movl %eax, i(%rip) //把寄存器的值寫回內(nèi)存
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架構(gòu)原子操作實現(xiàn)
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.無鎖隊列的實現(xiàn)
無鎖隊列適用于隊列push、pop非常頻繁的場景,效率要比mutex高很多