1. 程式人生 > >無鎖程式設計:lock-free原理;CAS;ABA問題

無鎖程式設計:lock-free原理;CAS;ABA問題

定義

無鎖程式設計是指在不使用鎖的情況下,在多執行緒環境下實現多變數的同步。即在沒有執行緒阻塞的情況下實現同步。這樣可以避免競態、死鎖等問題。

原理

CAS是指Compare-and-swap或Compare-and-Set 
CAS是一個原子操作,用於多執行緒環境下的同步。它比較記憶體中的內容和給定的值,只有當兩者相同時(說明其未被修改),才會修改記憶體中的內容。 
實現如下:

int compare_and_swap(int* reg, int oldval, int newval)
{
  ATOMIC();
  int old_reg_val = *reg;
  if (old_reg_val == oldval)
     *reg = newval;
  END_ATOMIC();
  return old_reg_val;
}

bool compare_and_swap(int *accum, int *dest, int newval)
{
  if (*accum == *dest) {
      *dest = newval;
      return true;
  } else {
      *accum = *dest;
      return false;
  }
}

返回bool值得好處是可以知道是否設定成功。

在實際環境中,使用的是:

bool __sync_bool_compare_and_swap (type *ptr, type oldval, type newval, ...)
type __sync_val_compare_and_swap (type *ptr, type oldval, type newval, ...)

在使用CAS時,需要先獲取操作變數的值並放到oldval中,之後呼叫cas函式,直到呼叫成功。例如給變數val賦值

while(true)
{
    int oldval=val;
    if(__sync_bool_compare_and_swap(&val, oldval, newval))
        break;
}

ABA問題

在多執行緒環境中,使用lock-free的CAS時,如果一個執行緒對變數修改2次,第2次修改後的值和第1次修改前的值相同,那麼可能就會出現ABA問題。以上面的例子為例: 
假設有兩個執行緒P1和P2,P1執行完int oldval=val後被其他執行緒搶佔。P2執行緒在此期間修改了val的值(可能多次修改),但最終val的值和修改前一樣。當P1執行緒之後執行CAS函式時,並不能發現這個問題。這就是ABA問題。

解決方法

一個常用的方法是新增額外的“tag”或“stamp”位來標記是指標是否被修改過。

作者:王中秋 本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段宣告,且在文章頁面明顯位置給出原文連線,否則保留追究法律責任的權利. 分類: java

相關推薦

程式設計lock-free原理CASABA問題

定義 無鎖程式設計是指在不使用鎖的情況下,在多執行緒環境下實現多變數的同步。即在沒有執行緒阻塞的情況下實現同步。這樣可以避免競態、死鎖等問題。 原理 CAS是指Compare-and-swap或Compare-and-Set  CAS是一個原子操作,用於多執行緒環境下的同步

程式設計lock-free原理

定義 原理 ABA問題 解決方法 定義 無鎖程式設計是指在不使用鎖的情況下,在多執行緒環境下實現多變數的同步。即在沒有執行緒阻塞的情況下實現同步。這樣可以避免競態、死鎖等問題。 原理 CAS是指Compare-and-swap或Comp

併發程式設計(三) 使用C++11實現stack(lock-free stack)

C++11中CAS實現: template< class T> struct atomic { public: bool compare_exchange_weak( T& expected, T desired,                    

(2.1.27.11)Java併發程式設計Lock之ReentrantReadWriteLock 讀寫分離獨享式重入

我們在介紹AbstractQueuedSynchronizer的時候介紹過,AQS支援獨佔式同步狀態獲取/釋放、共享式同步狀態獲取/釋放兩種模式,對應的典型應用分別是ReentrantLock和Semaphore AQS還可以混合兩種模式使用,讀寫鎖Reent

(2.1.27.13)Java併發程式設計Lock之CountDownLatch計數式獨享

CountDownLatch是一種java.util.concurrent包下一個同步工具類,它允許一個或多個執行緒等待直到在其他執行緒中一組操作執行完成。 相對於前文的鎖,它主要實現了: 呼叫指定次release後,才會釋放鎖 一、使用 public st

多執行緒 共享資源 同步 java Java多執行緒程式設計Lock

Java多執行緒程式設計:Lock   synchronized是java中的一個關鍵字,也就是說是Java語言內建的特性。那麼為什麼會出現Lock呢?   如果一個程式碼塊被synchronized修飾了,當一個執行緒獲取了對應的鎖,並執行該程式碼塊時,其他執行緒便只

的資料結構(Lock-Free)及CAS(Compare-and-Swap)機制

當同時存在讀寫執行緒時,預設情況下是不保證執行緒安全的,因而需要利用訊號量來進行執行緒同步(Synchronization),如關鍵程式碼段、互斥體等,同時作業系統也提供了相應的API。然而同步並不總是滿足條件的且有效率的,比如陷入核心時會有效能損失、死鎖、活鎖以及資源浪費

C++併發實戰19lock free程式設計

     涉及到並行/併發計算時,通常都會想到加鎖,加鎖可以保護共享的資料,不過也會存在一些問題: 1. 由於臨界區無法併發執行,進入臨界區就需要等待,加鎖使得效率的降低。多核CPU也不能發揮全部馬力 2. 在複雜的情況下,很容易造成死鎖,併發程序、執行緒之間無止境的互相等

【Linux】多執行緒程式設計--原子計數操作__sync_fetch_and_add等12個操作

 最近自己做了一些涉及多執行緒程式設計的專案,其中就涉及到多執行緒間計數操作、共享狀態或者統計相關時間次數,這些都需要在多執行緒之間共享變數和修改變數,如此就需要在多執行緒間對該變數進行互斥操作和訪問。         通常遇到多執行緒互斥的問題,首先想到的就是

我是如何一步步的在並行程式設計中將lock次數降到最低實現程式設計

在並行程式設計中,經常會遇到多執行緒間操作共享集合的問題,很多時候大家都很難逃避這個問題做到一種無鎖程式設計狀態,你也知道一旦給共享集合套上lock之後,併發和伸縮能力往往會造成很大影響,這篇就來談談如何儘可能的減少lock鎖次數甚至沒有。 一:緣由 1. 業務背景 昨天在review程式碼的時候,看到以前自

CAS演算法ReentrantLock,synchronized(JDK 1.6),悲觀/樂觀

> 悲觀鎖/樂觀鎖  悲觀鎖:總是假設最壞的情況,每次去拿資料的時候都認為別人會修改,所以每次在拿資料的時候都會上鎖,這樣別人想拿這個資料就會阻塞直到它拿到鎖。傳統的關係型資料庫裡邊就用到了很多這種鎖機制,比如行鎖,表鎖等,讀鎖,寫鎖等,都是在做操作之前先上鎖。再比如J

Java併發程式設計Lock

從Java 5之後,在java.util.concurrent.locks包下提供了另外一種方式來實現同步訪問,那就是Lock。   也許有朋友會問,既然都可以通過synchronized來實現同步訪問了,那麼為什麼還需要提供Lock?這個問題將在下面進行闡述。本文先從sy

(2.1.27.16)Java併發程式設計Lock之ConcurrentHashMap

ConcurrentHashMap 和 HashMap 的底層實現都是 陣列+連結串列或紅黑樹 構成的。 HashMap 的原始碼分析見:Java集合框架——HashMap原始碼分析 ConcurrentHashMap 相比 HashMap 支援多執行緒下的操

【轉載】Java併發程式設計Lock

Java併發程式設計:Lock   在上一篇文章中我們講到了如何使用關鍵字synchronized來實現同步訪問。本文我們繼續來探討這個問題,從Java 5之後,在java.util.concurrent.locks包下提供了另外一種方式來實現同步訪問,那就是Lock。

多執行緒程式設計

https://en.wikipedia.org/wiki/Compare-and-swap   http://blog.chinaunix.net/uid-25424552-id-3772253.html   https://coolshell.cn/artic

程式設計(CAS)

CAS操作 所謂CAS指Compare and Set(或Compare and Swap)。現在幾乎所有CPU指令都支援CAS,如X86的CMPXCHG彙編指令。CAS通常被視為無鎖(lock free)資料結構的基礎。CAS的C語言描述如下: int compare_

程式設計:c++11基於atomic實現共享讀寫(寫優先)

在多執行緒狀態下,對一個物件的讀寫需要加鎖,基於CAS指令的原子語句可以實現高效的執行緒間協調。關於CAS的概念參見下面的文章: 在c++11中CAS指令已經被封裝成了 非常方便使用的atomic模板類, 詳情參見: 以下程式碼利用atomic實現了

多執行緒模型下的程式設計

多執行緒模式是比較流行的一種併發程式設計模型,多執行緒程式設計的一個特點就是執行緒間共享記憶體空間;這可以降低執行緒間通訊的開銷,但卻引來了另外的一個難纏的問題:竟態條件!,因此,甚至有人對多執行緒模型提出了質疑,看這裡。在多執行緒程式設計模型下,解決竟態條件的傳統方法就是

程式設計和有程式設計效率對比

主要觀點包括: 程式簡單時,可以通過改程序序結構和鎖粒度,來提高效能 程式複雜時(需要考慮死鎖,優先順序繼承等),可通過無鎖程式設計CAS來提高效能 最近維護的一個網路伺服器遇到效能問題,於是就對原有的程式進行了較大的框架改動。改動最多的是執行緒工作模式與資料傳遞方式,最

C++程式設計資料,佇列等

1. Lamport's Lock-Free Ring Buffer        [Lamport, Comm. of ACM, 1977]      也就常說的單生產者-單消費者 的ringbuffer, 限制就是隻能一個讀執行緒(消費者),一個寫程序(生產者)。