java內(nèi)存模型二

      網(wǎng)友投稿 658 2025-04-01

      Java內(nèi)存模型

      volatile寫的內(nèi)存語(yǔ)義:當(dāng)寫一個(gè)volatile變量時(shí),JMM會(huì)把該線程對(duì)應(yīng)的本地內(nèi)存中的共享變量值刷新到主內(nèi)存。

      volatile讀的內(nèi)存語(yǔ)義如下:當(dāng)讀一個(gè)volatile變量時(shí),JMM會(huì)把該線程對(duì)應(yīng)的本地內(nèi)存置為無(wú)效。線程接下來(lái)將從主內(nèi)存中讀取共享變量。

      線程A寫一個(gè)volatile變量,實(shí)質(zhì)上是線程A向接下來(lái)將要讀這個(gè)volatile變量的某個(gè)線程發(fā)出了(其對(duì)共享變量所做修改的)消息。

      線程B讀一個(gè)volatile變量,實(shí)質(zhì)上是線程B接收了之前某個(gè)線程發(fā)出的(在寫這個(gè)volatile變量之前對(duì)共享變量所做修改的)消息。

      線程A寫一個(gè)volatile變量,隨后線程B讀這個(gè)volatile變量,這個(gè)過程實(shí)質(zhì)上是線程A通過主內(nèi)存向線程B發(fā)送消息。

      基于保守策略的JMM內(nèi)存屏障插入策略:

      在每個(gè)volatile寫操作的前面插入一個(gè)StoreStore屏障。

      在每個(gè)volatile寫操作的后面插入一個(gè)StoreLoad屏障。

      在每個(gè)volatile讀操作的后面插入一個(gè)LoadLoad屏障。

      在每個(gè)volatile讀操作的后面插入一個(gè)LoadStore屏障。

      public class VolatileBarrierExample { int a; volatile int v1 = 1; volatile int v2 = 2; void readAndWrite() { int i = v1; // 第一個(gè)volatile讀 int j = v2; // 第二個(gè)volatile讀 a = i + j; // 普通寫 v1 = i + 1; // 第一個(gè)volatile寫 v2 = j * 2; // 第二個(gè) volatile寫 } }

      線程A釋放一個(gè)鎖,實(shí)質(zhì)上是線程A向接下來(lái)將要獲取這個(gè)鎖的某個(gè)線程發(fā)出了(線程A對(duì)共享變量所做修改的)消息。

      線程B獲取一個(gè)鎖,實(shí)質(zhì)上是線程B接收了之前某個(gè)線程發(fā)出的(在釋放這個(gè)鎖之前對(duì)共享變量所做修改的)消息。

      線程A釋放鎖,隨后線程B獲取這個(gè)鎖,這個(gè)過程實(shí)質(zhì)上是線程A通過主內(nèi)存向線程B發(fā)送消息。

      ReentrantLock分為公平鎖和非公平鎖,我們首先分析公平鎖

      使用公平鎖時(shí),加鎖方法lock()調(diào)用軌跡如下。

      1)ReentrantLock:lock()。

      2)FairSync:lock()。

      3)AbstractQueuedSynchronizer:acquire(int arg)。

      4)ReentrantLock:tryAcquire(int acquires)。

      private volatile int state; protected final boolean tryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { if (!hasQueuedPredecessors() && compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } } else if (current == getExclusiveOwnerThread()) { int nextc = c + acquires; if (nextc < 0) throw new Error("Maximum lock count exceeded"); setState(nextc); return true; } return false; }

      從上面源代碼中我們可以看出,加鎖方法首先讀volatile變量state。

      在使用公平鎖時(shí),解鎖方法unlock()調(diào)用軌跡如下。

      1)ReentrantLock:unlock()。

      2)AbstractQueuedSynchronizer:release(int arg)。

      3)Sync:tryRelease(int releases)。

      protected final boolean tryRelease(int releases) { int c = getState() - releases; if (Thread.currentThread() != getExclusiveOwnerThread()) throw new IllegalMonitorStateException(); boolean free = false; if (c == 0) { free = true; setExclusiveOwnerThread(null); } setState(c); return free; }

      從上面的源代碼可以看出,在釋放鎖的最后setState 寫volatile變量state。

      公平鎖在釋放鎖的最后寫volatile變量state,在獲取鎖時(shí)首先讀這個(gè)volatile變量。根據(jù)volatile的happens-before規(guī)則,釋放鎖的線程在寫volatile變量之前可見的共享變量,在獲取鎖的線程讀取同一個(gè)volatile變量后將立即變得對(duì)獲取鎖的線程可見。

      非公平鎖的釋放和公平鎖完全一樣,所以這里僅僅分析非公平鎖的獲取。使用非公平鎖時(shí),加鎖方法lock()調(diào)用軌跡如下。

      1)ReentrantLock:lock()。

      2)NonfairSync:lock()。

      3)AbstractQueuedSynchronizer:compareAndSetState(int expect,int update)。

      /** * Sync object for non-fair locks */ static final class NonfairSync extends Sync { private static final long serialVersionUID = 7316153563782823691L; /** * Performs lock. Try immediate barge, backing up to normal * acquire on failure. */ final void lock() { if (compareAndSetState(0, 1)) setExclusiveOwnerThread(Thread.currentThread()); else acquire(1); } protected final boolean tryAcquire(int acquires) { return nonfairTryAcquire(acquires); } }

      java內(nèi)存模型二

      protected final boolean compareAndSetState(int expect, int update) { // See below for intrinsics setup to support this return unsafe.compareAndSwapInt(this, stateOffset, expect, update); }

      該方法以原子操作的方式更新state變量,Java的compareAndSet()方法調(diào)用簡(jiǎn)稱為CAS。JDK文檔對(duì)該方法的說(shuō)明如下:如果當(dāng)前狀態(tài)值等于預(yù)期值,則以原子方式將同步狀態(tài)設(shè)置為給定的更新值

      cas原理:如果程序是在多處理器上運(yùn)行 就在指令加上lock前綴

      lock前綴作用:

      1)確保對(duì)內(nèi)存的讀-改-寫操作原子執(zhí)行。在Pentium及Pentium之前的處理器中,帶有l(wèi)ock前綴的指令在執(zhí)行期間會(huì)鎖住總線,使得其他處理器暫時(shí)無(wú)法通過總線訪問內(nèi)存。很顯然,這會(huì)帶來(lái)昂貴的開銷。從Pentium 4、Intel Xeon及P6處理器開始,Intel使用緩存鎖定(Cache Locking)來(lái)保證指令執(zhí)行的原子性。緩存鎖定將大大降低lock前綴指令的執(zhí)行開銷。

      2)禁止該指令,與之前和之后的讀和寫指令重排序。

      3)把寫緩沖區(qū)中的所有數(shù)據(jù)刷新到內(nèi)存中。

      所以CAS同時(shí)具有volatile讀和volatile寫的內(nèi)存語(yǔ)義

      總結(jié):公平鎖和非公平鎖釋放時(shí),最后都要寫一個(gè)volatile變量state。

      公平鎖獲取時(shí),首先會(huì)去讀volatile變量。

      非公平鎖獲取時(shí),首先會(huì)用CAS更新volatile變量,這個(gè)操作同時(shí)具有volatile讀和volatile寫的內(nèi)存語(yǔ)義。

      鎖釋放-獲取的內(nèi)存語(yǔ)義的實(shí)現(xiàn)至少有下面兩種方式:

      1)利用volatile變量的寫-讀所具有的內(nèi)存語(yǔ)義。

      2)利用CAS所附帶的volatile讀和volatile寫的內(nèi)存語(yǔ)義。

      current并發(fā)包

      由于Java的CAS同時(shí)具有volatile讀和volatile寫的內(nèi)存語(yǔ)義,因此Java線程之間的通信現(xiàn)

      在有了下面4種方式。

      1)A線程寫volatile變量,隨后B線程讀這個(gè)volatile變量。

      2)A線程寫volatile變量,隨后B線程用CAS更新這個(gè)volatile變量。

      3)A線程用CAS更新一個(gè)volatile變量,隨后B線程用CAS更新這個(gè)volatile變量。

      4)A線程用CAS更新一個(gè)volatile變量,隨后B線程讀這個(gè)volatile變量。

      concurrent包的源代碼通用化的實(shí)現(xiàn)模式:

      首先,聲明共享變量為volatile。

      然后,使用CAS的原子條件更新來(lái)實(shí)現(xiàn)線程之間的同步。

      同時(shí),配合以volatile的讀/寫和CAS所具有的volatile讀和寫的內(nèi)存語(yǔ)義來(lái)實(shí)現(xiàn)線程之間的

      通信。

      AQS,非阻塞數(shù)據(jù)結(jié)構(gòu)和原子變量類(java.util.concurrent.atomic包中的類),這些concurrent包中的基礎(chǔ)類都是使用這種模式來(lái)實(shí)現(xiàn)的,而concurrent包中的高層類又是依賴于這些基礎(chǔ)類來(lái)實(shí)現(xiàn)的

      Java 任務(wù)調(diào)度

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:報(bào)表表格里有顏色怎么去除(表格上顏色怎么去掉)
      下一篇:制造與生產(chǎn)的聯(lián)系與區(qū)別(生產(chǎn)制造有什么區(qū)別)
      相關(guān)文章
      ASS亚洲熟妇毛茸茸PICS| 日韩一卡2卡3卡4卡新区亚洲| 国产成人亚洲精品狼色在线| 亚洲另类少妇17p| 亚洲精品又粗又大又爽A片| 亚洲春黄在线观看| 亚洲日本在线免费观看| 亚洲乱码卡三乱码新区| 亚洲国产激情在线一区| 亚洲国产福利精品一区二区| 亚洲成年人电影网站| 亚洲av午夜精品无码专区| 亚洲香蕉在线观看| 国产成人亚洲综合网站不卡| 亚洲精华液一二三产区| mm1313亚洲国产精品无码试看 | 亚洲av日韩精品久久久久久a| 亚洲码和欧洲码一码二码三码| 亚洲精品欧美综合四区| 精品久久久久久久久亚洲偷窥女厕| 色综合久久精品亚洲国产| 亚洲Av无码乱码在线播放| 亚洲一级片免费看| 亚洲级αV无码毛片久久精品| 亚洲成人中文字幕| 亚洲白色白色永久观看| 亚洲av无码专区在线| 亚洲色一区二区三区四区| 久久亚洲中文字幕无码| 亚洲精品高清一二区久久| 亚洲综合伊人久久大杳蕉| 亚洲AV成人一区二区三区AV| 久久综合亚洲色一区二区三区| 亚洲一欧洲中文字幕在线| 亚洲国产午夜精品理论片在线播放| 国产亚洲男人的天堂在线观看 | 中文字幕亚洲专区| 亚洲AV无码久久精品蜜桃| 亚洲国色天香视频| 亚洲AV无码一区二区三区性色| 亚洲午夜精品一级在线播放放 |