欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
樂(lè )觀(guān)鎖的一種實(shí)現方式——CAS

深入理解樂(lè )觀(guān)鎖與悲觀(guān)鎖一文中我們介紹過(guò)鎖。本文在這篇文章的基礎上,深入分析一下樂(lè )觀(guān)鎖的實(shí)現機制,介紹什么是CAS、CAS的應用以及CAS存在的問(wèn)題等。

線(xiàn)程安全

眾所周知,Java是多線(xiàn)程的。但是,Java對多線(xiàn)程的支持其實(shí)是一把雙刃劍。一旦涉及到多個(gè)線(xiàn)程操作共享資源的情況時(shí),處理不好就可能產(chǎn)生線(xiàn)程安全問(wèn)題。線(xiàn)程安全性可能是非常復雜的,在沒(méi)有充足的同步的情況下,多個(gè)線(xiàn)程中的操作執行順序是不可預測的。

Java里面進(jìn)行多線(xiàn)程通信的主要方式就是共享內存的方式,共享內存主要的關(guān)注點(diǎn)有兩個(gè):可見(jiàn)性和有序性。加上復合操作的原子性,我們可以認為Java的線(xiàn)程安全性問(wèn)題主要關(guān)注點(diǎn)有3個(gè):可見(jiàn)性、有序性和原子性。

Java內存模型(JMM)解決了可見(jiàn)性和有序性的問(wèn)題,而鎖解決了原子性的問(wèn)題。這里不再詳細介紹JMM及鎖的其他相關(guān)知識。但是我們要討論一個(gè)問(wèn)題,那就是鎖到底是不是有利無(wú)弊的?

鎖存在的問(wèn)題

Java在JDK1.5之前都是靠synchronized關(guān)鍵字保證同步的,這種通過(guò)使用一致的鎖定協(xié)議來(lái)協(xié)調對共享狀態(tài)的訪(fǎng)問(wèn),可以確保無(wú)論哪個(gè)線(xiàn)程持有共享變量的鎖,都采用獨占的方式來(lái)訪(fǎng)問(wèn)這些變量。獨占鎖其實(shí)就是一種悲觀(guān)鎖,所以可以說(shuō)synchronized是悲觀(guān)鎖。

悲觀(guān)鎖機制存在以下問(wèn)題:

在多線(xiàn)程競爭下,加鎖、釋放鎖會(huì )導致比較多的上下文切換和調度延時(shí),引起性能問(wèn)題。

一個(gè)線(xiàn)程持有鎖會(huì )導致其它所有需要此鎖的線(xiàn)程掛起。

如果一個(gè)優(yōu)先級高的線(xiàn)程等待一個(gè)優(yōu)先級低的線(xiàn)程釋放鎖會(huì )導致優(yōu)先級倒置,引起性能風(fēng)險。

而另一個(gè)更加有效的鎖就是樂(lè )觀(guān)鎖。所謂樂(lè )觀(guān)鎖就是,每次不加鎖而是假設沒(méi)有沖突而去完成某項操作,如果因為沖突失敗就重試,直到成功為止。

與鎖相比,volatile變量是一個(gè)更輕量級的同步機制,因為在使用這些變量時(shí)不會(huì )發(fā)生上下文切換和線(xiàn)程調度等操作,但是volatile不能解決原子性問(wèn)題,因此當一個(gè)變量依賴(lài)舊值時(shí)就不能使用volatile變量。因此對于同步最終還是要回到鎖機制上來(lái)。

樂(lè )觀(guān)鎖

樂(lè )觀(guān)鎖( Optimistic Locking)其實(shí)是一種思想。相對悲觀(guān)鎖而言,樂(lè )觀(guān)鎖假設認為數據一般情況下不會(huì )造成沖突,所以在數據進(jìn)行提交更新的時(shí)候,才會(huì )正式對數據的沖突與否進(jìn)行檢測,如果發(fā)現沖突了,則讓返回用戶(hù)錯誤的信息,讓用戶(hù)決定如何去做。

上面提到的樂(lè )觀(guān)鎖的概念中其實(shí)已經(jīng)闡述了他的具體實(shí)現細節:主要就是兩個(gè)步驟:沖突檢測和數據更新。其實(shí)現方式有一種比較典型的就是Compare and Swap(CAS)。

CAS

CAS是項樂(lè )觀(guān)鎖技術(shù),當多個(gè)線(xiàn)程嘗試使用CAS同時(shí)更新同一個(gè)變量時(shí),只有其中一個(gè)線(xiàn)程能更新變量的值,而其它線(xiàn)程都失敗,失敗的線(xiàn)程并不會(huì )被掛起,而是被告知這次競爭中失敗,并可以再次嘗試。

CAS 操作包含三個(gè)操作數 —— 內存位置(V)、預期原值(A)和新值(B)。如果內存位置的值與預期原值相匹配,那么處理器會(huì )自動(dòng)將該位置值更新為新值。否則,處理器不做任何操作。無(wú)論哪種情況,它都會(huì )在 CAS 指令之前返回該位置的值。(在 CAS 的一些特殊情況下將僅返回 CAS 是否成功,而不提取當前值。)CAS 有效地說(shuō)明了“我認為位置 V 應該包含值 A;如果包含該值,則將 B 放到這個(gè)位置;否則,不要更改該位置,只告訴我這個(gè)位置現在的值即可?!边@其實(shí)和樂(lè )觀(guān)鎖的沖突檢查 數據更新的原理是一樣的。

這里再強調一下,樂(lè )觀(guān)鎖是一種思想。CAS是這種思想的一種實(shí)現方式。

Java對CAS的支持

在JDK1.5 中新增java.util.concurrent(J.U.C)就是建立在CAS之上的。相對于對于synchronized這種阻塞算法,CAS是非阻塞算法的一種常見(jiàn)實(shí)現。所以J.U.C在性能上有了很大的提升。

我們以java.util.concurrent中的AtomicInteger為例,看一下在不使用鎖的情況下是如何保證線(xiàn)程安全的。主要理解getAndIncrement方法,該方法的作用相當于  i 操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class AtomicInteger extends Number implements java.io.Serializable { 
        private volatile int value; 
    public final int get() { 
        return value; 
    
    public final int getAndIncrement() { 
        for (;;) { 
            int current = get(); 
            int next = current 1
            if (compareAndSet(current, next)) 
                return current; 
        
    
    public final boolean compareAndSet(int expect, int update) { 
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update); 
    
}

在沒(méi)有鎖的機制下需要字段value要借助volatile原語(yǔ),保證線(xiàn)程間的數據是可見(jiàn)的。這樣在獲取變量的值的時(shí)候才能直接讀取。然后來(lái)看看 i是怎么做到的。

getAndIncrement采用了CAS操作,每次從內存中讀取數據然后將此數據和 1后的結果進(jìn)行CAS操作,如果成功就返回結果,否則重試直到成功為止。而compareAndSet利用JNI來(lái)完成CPU指令的操作。

ABA問(wèn)題

CAS會(huì )導致“ABA問(wèn)題”。

CAS算法實(shí)現一個(gè)重要前提需要取出內存中某時(shí)刻的數據,而在下時(shí)刻比較并替換,那么在這個(gè)時(shí)間差類(lèi)會(huì )導致數據的變化。

比如說(shuō)一個(gè)線(xiàn)程one從內存位置V中取出A,這時(shí)候另一個(gè)線(xiàn)程two也從內存中取出A,并且two進(jìn)行了一些操作變成了B,然后two又將V位置的數據變成A,這時(shí)候線(xiàn)程one進(jìn)行CAS操作發(fā)現內存中仍然是A,然后one操作成功。盡管線(xiàn)程one的CAS操作成功,但是不代表這個(gè)過(guò)程就是沒(méi)有問(wèn)題的。

部分樂(lè )觀(guān)鎖的實(shí)現是通過(guò)版本號(version)的方式來(lái)解決ABA問(wèn)題,樂(lè )觀(guān)鎖每次在執行數據的修改操作時(shí),都會(huì )帶上一個(gè)版本號,一旦版本號和數據的版本號一致就可以執行修改操作并對版本號執行 1操作,否則就執行失敗。因為每次操作的版本號都會(huì )隨之增加,所以不會(huì )出現ABA問(wèn)題,因為版本號只會(huì )增加不會(huì )減少。

總結

Java中的線(xiàn)程安全問(wèn)題至關(guān)重要,要想保證線(xiàn)程安全,就需要鎖機制。鎖機制包含兩種:樂(lè )觀(guān)鎖與悲觀(guān)鎖。悲觀(guān)鎖是獨占鎖,阻塞鎖。樂(lè )觀(guān)鎖是非獨占鎖,非阻塞鎖。有一種樂(lè )觀(guān)鎖的實(shí)現方式就是CAS ,這種算法在JDK 1.5中引入的java.util.concurrent中有廣泛應用。但是值得注意的是這種算法會(huì )存在A(yíng)BA問(wèn)題。

CAS與對象創(chuàng )建

另外,CAS還有一個(gè)應用,那就是在JVM創(chuàng )建對象的過(guò)程中。對象創(chuàng )建在虛擬機中是非常頻繁的。即使是僅僅修改一個(gè)指針所指向的位置,在并發(fā)情況下也不是線(xiàn)程安全的,可能正在給對象A分配內存空間,指針還沒(méi)來(lái)得及修改,對象B又同時(shí)使用了原來(lái)的指針來(lái)分配內存的情況。解決這個(gè)問(wèn)題的方案有兩種,其中一種就是采用CAS配上失敗重試的方式保證更新操作的原子性。

參考資料

非阻塞同步算法與CAS(Compare and Swap)無(wú)鎖算法

CAS原理分析

Java CAS 和ABA問(wèn)題

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
并發(fā)減庫存
Java鎖機制(二)
#深入淺出樂(lè )觀(guān)鎖與悲觀(guān)鎖
淺談 Java 并發(fā)下的樂(lè )觀(guān)鎖
java并發(fā)(3):并發(fā)工具集
關(guān)于Java鎖機制面試官會(huì )怎么問(wèn),深刻易懂
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久