C++11中的原子操作(atomic operation)和自旋锁
C++11中的原子操作(atomic operation)
- 1. 原子操作
- 2. 自旋鎖
- 3. 原子操作和使用互斥鎖和自旋鎖的速度對比
1. 原子操作
??所謂的原子操作,取的就是“原子是最小的、不可分割的最小個體”的意義,它表示在多個線程訪問同一個全局資源的時候,能夠確保所有其他的線程都不在同一時間內訪問相同的資源。
??我們在原子操作之前在多線程同步中防止發生數據競爭的操作是加互斥鎖,但互斥鎖是操作系統這一層級的,最終映射到CPU上也是一堆指令,是指令就必然會帶來額外的開銷;既然CPU指令是多線程不可再分的最小單元,那我們如果有辦法將代碼語句和指令對應起來,不就不需要引入互斥鎖從而提高性能了嗎? 而這個對應關系就是所謂的原子操作;
??在新標準C++11,引入了原子操作的概念,并通過這個新的頭文件提供了多種原子操作數據類型,例如,atomic_bool,atomic_int等等,如果我們在多個線程中對這些類型的共享資源進行操作,編譯器將保證這些操作都是原子性的,也就是說,確保任意時刻只有一個線程對這個資源進行訪問,編譯器將保證,多個線程訪問這個共享資源的正確性。從而避免了鎖的使用,提高了效率。
2. 自旋鎖
??自旋鎖是一種基礎的同步原語,用于保障對共享數據的互斥訪問。與互斥鎖的相比,在獲取鎖失敗的時候不會使得線程阻塞而是一直自旋嘗試獲取鎖。當線程等待自旋鎖的時候,CPU不能做其他事情,而是一直處于輪詢忙等的狀態。
??自旋鎖主要適用于被持有時間短,線程不希望在重新調度上花過多時間的情況。實際上許多其他類型的鎖在底層使用了自旋鎖實現,例如多數互斥鎖在試圖獲取鎖的時候會先自旋一小段時間,然后才會休眠。如果在持鎖時間很長的場景下使用自旋鎖,則會導致CPU在這個線程的時間片用盡之前一直消耗在無意義的忙等上,造成計算資源的浪費。
自旋鎖相關API:
int pthread_spin_init(pthread_spinlock_t *, int); //初始化自旋鎖 int pthread_spin_lock(pthread_spinlock_t *); //獲得一個自旋鎖 int pthread_spin_trylock(pthread_spinlock_t *); //嘗試獲取一個自旋鎖 int pthread_spin_unlock(pthread_spinlock_t *);//釋放(解鎖)一個自旋鎖 int pthread_spin_destroy(pthread_spinlock_t *); //銷毀一個自旋鎖使用自旋鎖注意:
??由于自旋時不釋放CPU,因而持有自旋鎖的線程應該盡快釋放自旋鎖,否則等待該自旋鎖的線程會一直在哪里自旋,這就會浪費CPU時間。
持有自旋鎖的線程在sleep之前應該釋放自旋鎖以便其他線程可以獲得該自旋鎖
3. 原子操作和使用互斥鎖和自旋鎖的速度對比
單線程無鎖速度最快,但應用場合受限;
多線程無鎖速度第二快,但結果不對,未保護臨界代碼段;
多線程原子鎖第三快,且結果正確;
多線程互斥量較慢,慢與原子鎖近10倍,結果正確;
多線程自旋鎖最慢,慢與原子鎖30倍,結果正確。
結論:原子鎖速度最快,互斥量和自旋鎖都用保護多線程共享資源。
??自旋鎖是一種非阻塞鎖,也就是說,如果某線程需要獲取自旋鎖,但該鎖已經被其他線程占用時,該線程不會被掛起,而是在不斷的消耗CPU的時間,不停的試圖獲取自旋鎖。
??互斥量是阻塞鎖,當某線程無法獲取互斥量時,該線程會被直接掛起,該線程不再消耗CPU時間,當其他線程釋放互斥量后,操作系統會激活那個被掛起的線程,讓其投入運行。
總結
以上是生活随笔為你收集整理的C++11中的原子操作(atomic operation)和自旋锁的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 第一次团队合作计划
- 下一篇: VC操作word和excel文件,查询与