2015-10-14 90 views
-1

AtomicReference實例使用Unsafe CAS操作來利用處理器指令進行鎖定。但我有點困惑,它在複雜對象的情況下如何工作。AtomicReference如何使用CAS來處理複雜對象

例如讓我們假設我有一個Person類(id,firstName,lastName)的實例。我正在將對象實例共享給多個線程t1,t2和t3。由於操作應該是原子的,所以不要共享Person類對象實例,我會將該對象包裝到AtomicReference實例中並與所有線程共享。

現在線程t1只更新firstName,線程t2只更新lastName而線程t3更新firstName和lastName。之後,每個線程都會調用compareAndSet方法來反映新的更改。

此外,我正在使用易失性參考,以便寫入可以發生在主內存和所有線程都可見。

我想明白了:

  1. 在上述情況下,當compareAndSet被調用,有什麼期望之間將被比較的東西和新的價值Person類的實例(如ID,名字,姓氏)?

  2. 假設線程t1已更新firstName並調用compareAndSet。線程t2已經更新了lastName,並且只是要調用compareAndSet。在這種情況下,AtomicReference如何保證線程t2不會擦除線程t1所做的更改,即更新firstName?

  3. 假設2個線程t1和t2同時調用了compareAndSet那麼誰將贏得比賽以及其他線程誰會失敗呢?

回答

0

一個AtomicReference整點是代表

可以用原子方式更新的對象引用。

它沒有阻止你自動修改引用指向的對象。

在,什麼是Person類 實例(例如ID,名字,姓氏)的事情 預期之間將進行比較和新的價值上面的場景時compareAndSet被調用?

沒有那些。 compareAndSet將使用引用相等來驗證當前引用等於expected引用,即。 ==。根據JavaDoc

原子方式將該值設置爲給定的更新值,如果當前 值==預期值。

它不知道或關心引用的類型,因此不知道或關心其成員或定義它們的邏輯。

假設2個線程T1和T2稱爲compareAndSet在同一時間,然後 誰就能贏得比賽,會發生什麼其他的線程誰的損失?

訂單未定義。 compareAndSet只在當前參考值等於給定預期參考值時纔有效。該方法將返回

true如果成功。 false return表示實際值爲 不等於預期值。

2

如果您有共享的可變對象Person,那麼AtomicReference根本沒有任何幫助。您需要使Person不可變,並在每次要應用更改時創建一個新的Person。這樣,線程更新多少個字段並不重要。因此,假設你有這樣一成不變Person類:

public class Person { 
    public final int id; 
    public final String firstName, lastName; 

    public Person(int id, String firstName, String lastName) { 
     this.id = id; 
     this.firstName = firstName; 
     this.lastName = lastName; 
    } 
} 

然後你的線程可以執行以下操作

AtomicReference<Person> ref; // shared reference 

public void updateFirstName(String firstName) { 
    Person curPerson, newPerson; 
    do { 
     curPerson = ref.get(); 
     newPerson = new Person(curPerson.id, firstName, curPerson.lastName); 
    } while (!ref.compareAndSet(curPerson, newPerson)); 
} 

public void updateLastName(String lastName) { 
    Person curPerson, newPerson; 
    do { 
     curPerson = ref.get(); 
     newPerson = new Person(curPerson.id, curPerson.firstName, lastName); 
    } while (!ref.compareAndSet(curPerson, newPerson)); 
} 

public void updateName(String firstName, String lastName) { 
    Person curPerson, newPerson; 
    do { 
     curPerson = ref.get(); 
     newPerson = new Person(curPerson.id, firstName, lastName); 
    } while (!ref.compareAndSet(curPerson, newPerson)); 
} 

調用這些方法,你將更新Person作爲一個整體,不會有任何競爭條件。

至於你的第三個問題,沒有說明誰會贏,但是失敗的線程只會再做一次迭代並相應地更新另一個字段,所以你最終會同時更新這兩個字段。