日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

volatile原理与技巧

發(fā)布時(shí)間:2025/7/14 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 volatile原理与技巧 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

轉(zhuǎn)自http://www.iteye.com/topic/109150

volatile, 用更低的代價(jià)替代同步

為什么 使用volatile比同步代價(jià)更低??
同步的代價(jià), 主要由其覆蓋范圍決定, 如果可以降低同步的覆蓋范圍, 則可以大幅提升程序性能.

而volatile的覆蓋范圍僅僅變量級(jí)別的. 因此它的同步代價(jià)很低.

?

volatile原理是什么?
volatile的語(yǔ)義, 其實(shí)是告訴處理器, 不要將我放入工作內(nèi)存, 請(qǐng)直接在主存操作我.(工作內(nèi)存詳見(jiàn)java內(nèi)存模型)

因此, 當(dāng)多核或多線程在訪問(wèn)該變量時(shí), 都將直接 操作 主存, 這從本質(zhì)上, 做到了變量共享.

?

volatile的有什么優(yōu)勢(shì)??
1, 更大的程序吞吐量
2, 更少的代碼實(shí)現(xiàn)多線程
3, 程序的伸縮性較好
4, 比較好理解, 無(wú)需太高的學(xué)習(xí)成本

?

volatile有什么劣勢(shì)??
1, 容易出問(wèn)題
2, 比較難設(shè)計(jì)

?

volatile運(yùn)算存在臟數(shù)據(jù)問(wèn)題

volatile僅僅能保證變量可見(jiàn)性, 無(wú)法保證原子性.

?

volatile的race condition示例:

Java代碼??
  • public?class?TestRaceCondition?{??
  • ????private?volatile?int?i?=?0;??
  • ??
  • ????public?void?increase()?{??
  • ???????i++;??
  • ????}??
  • ??
  • ????public?int?getValue()?{??
  • ???????return?i;??
  • ????}??
  • }??
  • ?

    當(dāng)多線程執(zhí)行increase方法時(shí), 是否能保證它的值會(huì)是線性遞增的呢??
    答案是否定的.

    ?

    原因:
    這里的increase方法, 執(zhí)行的操作是i++, 即 i = i + 1;
    針對(duì)i = i + 1, 在多線程中的運(yùn)算, 本身需要改變i的值.
    如果, 在i已從內(nèi)存中取到最新值, 但未與1進(jìn)行運(yùn)算, 此時(shí)其他線程已數(shù)次將運(yùn)算結(jié)果賦值給i.
    則當(dāng)前線程結(jié)束時(shí), 之前的數(shù)次運(yùn)算結(jié)果都將被覆蓋.

    即, 執(zhí)行100次increase, 可能結(jié)果是 < 100.
    一般來(lái)說(shuō), 這種情況需要較高的壓力與并發(fā)情況下, 才會(huì)出現(xiàn).

    ?

    如何避免這種情況??
    解決以上問(wèn)題的方法:
    一種是 操作時(shí), 加上同步.
    這種方法, 無(wú)疑將大大降低程序性能, 且違背了volatile的初衷.

    ?

    第二種方式是, 使用硬件原語(yǔ)(CAS), 實(shí)現(xiàn)非阻塞算法
    從CPU原語(yǔ)上, 支持變量級(jí)別的低開(kāi)銷同步.

    ?

    CPU原語(yǔ)-比較并交換(CompareAndSet),實(shí)現(xiàn)非阻塞算法

    什么是CAS??
    cas是現(xiàn)代CPU提供給并發(fā)程序使用的原語(yǔ)操作. 不同的CPU有不同的使用規(guī)范.

    在 Intel 處理器中,比較并交換通過(guò)指令的 cmpxchg 系列實(shí)現(xiàn)。
    PowerPC 處理器有一對(duì)名為“加載并保留”和“條件存儲(chǔ)”的指令,它們實(shí)現(xiàn)相同的目地;
    MIPS 與 PowerPC 處理器相似,除了第一個(gè)指令稱為“加載鏈接”。

    CAS 操作包含三個(gè)操作數(shù) —— 內(nèi)存位置(V)、預(yù)期原值(A)和新值(B)

    ?

    什么是非阻塞算法??
    一個(gè)線程的失敗或掛起不應(yīng)該影響其他線程的失敗或掛起.這類算法稱之為非阻塞(nonblocking)算法

    對(duì)比阻塞算法:
    如果有一類并發(fā)操作, 其中一個(gè)線程優(yōu)先得到對(duì)象監(jiān)視器的鎖, 當(dāng)其他線程到達(dá)同步邊界時(shí), 就會(huì)被阻塞.
    直到前一個(gè)線程釋放掉鎖后, 才可以繼續(xù)競(jìng)爭(zhēng)對(duì)象鎖.(當(dāng)然,這里的競(jìng)爭(zhēng)也可是公平的, 按先來(lái)后到的次序)

    ?

    CAS 原理:

    我認(rèn)為位置 V 應(yīng)該包含值 A;如果包含該值,則將 B 放到這個(gè)位置;否則,不要更改該位置,只告訴我這個(gè)位置現(xiàn)在的值即可。

    ?

    CAS使用示例(jdk 1.5 并發(fā)包 AtomicInteger類分析:)

    ?

    Java代碼??
  • public?final?int?getAndSet(int?newValue)?{??
  • ?????for?(;;)?{??
  • ?????????int?current?=?get();??
  • ?????????if?(compareAndSet(current,?newValue))??
  • ?????????????return?current;??
  • ?????}??
  • ?}??
  • ??
  • ?public?final?boolean?compareAndSet(int?expect,?int?update)?{??
  • ?????return?unsafe.compareAndSwapInt(this,?valueOffset,?expect,?update);??
  • ?}??
  • ?

    這個(gè)方法是, AtomicInteger類的常用方法, 作用是, 將變量設(shè)置為指定值, 并返回設(shè)置前的值.
    它利用了cpu原語(yǔ)compareAndSet來(lái)保障值的唯一性.

    另, AtomicInteger類中, 其他的實(shí)用方法, 也是基于同樣的實(shí)現(xiàn)方式.
    比如 getAndIncrement, getAndDecrement, getAndAdd等等.

    ?

    CAS語(yǔ)義上存在的 " ABA 問(wèn)題"

    什么是ABA問(wèn)題?
    假設(shè), 第一次讀取V地址的A值, 然后通過(guò)CAS來(lái)判斷V地址的值是否仍舊為A, 如果是, 就將B的值寫(xiě)入V地址,覆蓋A值.

    但是, 語(yǔ)義上, 有一個(gè)漏洞, 當(dāng)?shù)谝淮巫x取V的A值, 此時(shí), 內(nèi)存V的值變?yōu)锽值, 然后在未執(zhí)行CAS前, 又變回了A值.
    此時(shí), CAS再執(zhí)行時(shí), 會(huì)判斷其正確的, 并進(jìn)行賦值.

    ?

    這種判斷值的方式來(lái)斷定內(nèi)存是否被修改過(guò), 針對(duì)某些問(wèn)題, 是不適用的.

    為了解決這種問(wèn)題, jdk 1.5并發(fā)包提供了AtomicStampedReference(有標(biāo)記的原子引用)類, 通過(guò)控制變量值的版本來(lái)保證CAS正確性.

    ?

    其實(shí), 大部分通過(guò)值的變化來(lái)CAS, 已經(jīng)夠用了.

    ?

    jdk1.5原子包介紹(基于volatile)

    包的特色:
    1, 普通原子數(shù)值類型AtomicInteger, AtomicLong提供一些原子操作的加減運(yùn)算.

    2, 使用了解決臟數(shù)據(jù)問(wèn)題的經(jīng)典模式-"比對(duì)后設(shè)定", 即 查看主存中數(shù)據(jù)是否與預(yù)期提供的值一致,如果一致,才更新.

    3, 使用AtomicReference可以實(shí)現(xiàn)對(duì)所有對(duì)象的原子引用及賦值.包括Double與Float,
    但不包括對(duì)其的計(jì)算.浮點(diǎn)的計(jì)算,只能依靠同步關(guān)鍵字或Lock接口來(lái)實(shí)現(xiàn)了.

    4, 對(duì)數(shù)組元素里的對(duì)象,符合以上特點(diǎn)的, 也可采用原子操作.包里提供了一些數(shù)組原子操作類
    AtomicIntegerArray, AtomicLongArray等等.

    5, 大幅度提升系統(tǒng)吞吐量及性能.

    ?

    具體使用, 詳解java doc.

    轉(zhuǎn)載于:https://www.cnblogs.com/balaamwe/archive/2011/11/22/2259081.html

    總結(jié)

    以上是生活随笔為你收集整理的volatile原理与技巧的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。