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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

易语言 字段重复_使对易失性字段的操作原子化

發(fā)布時間:2023/12/3 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 易语言 字段重复_使对易失性字段的操作原子化 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

易語言 字段重復(fù)

總覽

易失性字段的預(yù)期行為是,它們在多線程應(yīng)用程序中的行為應(yīng)與在單線程應(yīng)用程序中的行為相同。 禁止它們表現(xiàn)相同的方式,但是不能保證它們表現(xiàn)相同的方式。

Java 5.0+中的解決方案是使用AtomicXxxx類,但是這些類在內(nèi)存(它們添加標(biāo)頭和填充),性能(它們添加引用和對其相對位置的控制很少)方面效率較低,從語法上講,它們不是明確使用。

恕我直言,一個簡單的解決方案,如果可變字段能夠像預(yù)期的那樣起作用,那么JVM必須在AtomicFields中支持的方式是當(dāng)前JMM(Java內(nèi)存模型)中所禁止的,但不能保證。

為什么要使字段

volatile字段的優(yōu)點是,它們在線程中可見,并且某些避免重新讀取它們的優(yōu)化已被禁用,因此即使您沒有更改它們,也始終要再次檢查當(dāng)前值。

例如不揮發(fā)

Thread 2: int a = 5;Thread 1: a = 6;

(后來)

Thread 2: System.out.println(a); // prints 5 or 6

具有揮發(fā)性

Thread 2: volatile int a = 5;Thread 1: a = 6;

(后來)

Thread 2: System.out.println(a); // prints 6 given enough time.

為什么不一直使用

易失的讀寫訪問速度要慢得多。 當(dāng)您寫入易失性字段時,它將使整個CPU管道停頓下來,以確保已將數(shù)據(jù)寫入緩存。 否則,即使在同一線程中,下一次讀取該值也有可能會看到舊值(請參閱AtomicLong.lazySet(),這樣可以避免停頓管道)

懲罰可能會慢10倍左右,您不想在每次訪問時都這樣做。

一個重要的限制是,即使您可能認(rèn)為對字段的操作也不是原子的。 甚至比通常情況更糟,沒有區(qū)別。 也就是說,它似乎可以工作很長時間甚至幾年,并且由于偶然的更改(例如所用的Java版本),甚至對象加載到內(nèi)存中而突然/隨機(jī)中斷。 例如,在運行程序之前加載了哪些程序。

例如更新值

Thread 2: volatile int a = 5;Thread 1: a += 1; Thread 2: a += 2;

(后來)

Thread 2: System.out.println(a); // prints 6, 7 or 8 even given enough time.

這是一個問題,因為對a的讀取和對a的寫入是分別完成的,并且您可以獲得競爭條件。 99%以上的時間它會表現(xiàn)出預(yù)期,但有時卻不會。

你能為這個做什么?

您需要使用AtomicXxxx類。 這些將易失性字段包裝為具有預(yù)期行為的操作。

Thread 2: AtomicInteger a = new AtomicInteger(5);Thread 1: a.incrementAndGet(); Thread 2: a.addAndGet(2);

(后來)

Thread 2: System.out.println(a); // prints 8 given enough time.

我有什么建議?

JVM具有一種按預(yù)期方式運行的方法,唯一令人驚訝的事情是您需要使用特殊的類來完成JMM不能保證的工作。 我建議更改JMM以支持當(dāng)前由并發(fā)AtomicClasses提供的行為。

在每種情況下,單線程行為都是不變的。 沒有看到競爭條件的多線程程序?qū)⒈憩F(xiàn)相同。 區(qū)別在于,多線程程序不必查看競爭條件,而可以更改基本行為。

當(dāng)前方法 建議語法 筆記
x.getAndIncrement() x ++或x + = 1
x.incrementAndGet() ++ x
x.getAndDecrment() x–或x-= 1
x.decrementAndGet() -X
x.addAndGet(y) (x + = y)
x.getAndAdd(y) ((x + = y)-y)
x.compareAndSet(e,y) (x == e?x = y,true:false) 需要添加逗號語法
在其他語言中使用。


所有原始類型(例如布爾,字節(jié),short,int,long,float和double)都可以支持這些操作。

可以支持其他賦值運算符,例如:

當(dāng)前方法 建議語法 筆記
原子乘法 x * = 2;
原子減法 x-= y;
原子分裂 x / = y;
原子模量 x%= y;
原子位移 x << = y;
原子位移 x >> = z;
原子位移 x >>> = w;
原子和 x&=?y; 清除位
原子或 x | = z; 設(shè)置位
原子異或 x ^ = w; 翻轉(zhuǎn)位

有什么風(fēng)險?

這可能會破壞依賴于這些操作的代碼,這些代碼有時會由于競爭條件而失敗。

可能無法以線程安全的方式支持更復(fù)雜的表達(dá)式。 這可能會導(dǎo)致令人驚訝的錯誤,因為代碼看起來像是正常的,但事實并非如此。 永遠(yuǎn)不會比當(dāng)前狀態(tài)更糟。

JEP 193 –增強(qiáng)揮發(fā)性

有一個JEP 193將此功能添加到Java。 一個例子是:

class Usage {volatile int count;int incrementCount() {return count.volatile.incrementAndGet();} }

恕我直言,這種方法有一些限制。

  • 語法是相當(dāng)重要的變化。 更改JMM可能不需要更改Java語法,也可能不需要更改編譯器。
  • 這是一個不太通用的解決方案。 支持諸如體積+ =數(shù)量之類的操作可能很有用; 這些是雙重類型。
  • 開發(fā)人員要了解為什么他/她應(yīng)該使用此代碼而不是x ++ ,這會給開發(fā)人員帶來更多負(fù)擔(dān);

我不相信使用更麻煩的語法可以更清楚地了解正在發(fā)生的事情。 考慮以下示例:

volatile int a, b;a += b;

要么

a.volatile.addAndGet(b.volatile);

要么

AtomicInteger a, b;a.addAndGet(b.get());

作為行,這些操作中的哪個是原子的。 他們都不回答,但是采用Intel TSX的系統(tǒng)可以使這些原子化,如果您要更改這些代碼行中的任何行為,我都可以使a + = b; 而不是發(fā)明一種新的語法,該語法在大多數(shù)情況下會做同樣的事情,但是可以保證一種語法,而不能保證另一種語法。

結(jié)論

如果JMM保證等效的單線程操作的行為符合多線程代碼的預(yù)期,則可以消除使用AtomicInteger和AtomicLong的許多語法和性能開銷。

可以通過使用字節(jié)碼檢測將該功能添加到Java的早期版本中。

翻譯自: https://www.javacodegeeks.com/2014/07/making-operations-on-volatile-fields-atomic.html

易語言 字段重復(fù)

總結(jié)

以上是生活随笔為你收集整理的易语言 字段重复_使对易失性字段的操作原子化的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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