atomic java_在Java中添加@atomic操作
atomic java
總覽
原子操作如何在Java中工作,OpenJDK / Hotspot中是否存在可以轉換為原子的當前替代方法。
反饋
在我以前的文章中, 對可變字段進行原子操作。 有幾次指出,不管善意如何,“修復”先前的行為都不太可能繼續進行。
替代方法是添加@atomic注釋。 這樣做的好處是僅適用于新代碼,而不會冒險破壞舊代碼。
注意:故意使用小寫字母,因為它*不*遵循當前的編碼約定。
原子操作
任何帶有@atomic列出的字段都將使整個表達式具有原子性。 非易失性和非原子性變量可以在開始時讀取,或者在表達式完成后進行設置。 該表達式本身可能需要在某些平臺,CAS操作或TSX上鎖定,具體取決于CPU技術。
如果僅讀取字段,或者也只寫入一個字段,則該字段與volatile相同。
原子布爾
當前,AtomicBoolean使用4個字節,外加一個對象標頭,并帶有可能的填充(以及引用)。如果該字段是內聯的,則可能看起來像這樣
@atomic boolean flag; // toggle the flag. this.flag = !this.flag;但是如何運作? 并非所有平臺都支持1字節原子操作,例如Unsafe確實具有1字節CAS操作。 這可以通過掩膜來完成。
// possible replacement. while(true) {int num = Unsafe.getUnsafe().getVolatileInt(this, FLAG_OFFSET & ~3); // word align the access.int value ^= 1 << ~(0xFF << (FLAG_OFFSET & 3) * 8) ;if (Unsafe.getUnsafe().compareAndSwapInt(this, FLAG_OFFSET & ~3, num, value))break; }原子雙
不支持的類型是AtomicDouble,但這是AtomicLong的變體。 考慮這個例子。
@atomic double a = 1; volatile double b = 2;a += b;今天如何實施?
while(true) {double _b = Unsafe.getUnsafe().getVolatileDouble(this, B_OFFSET);double _a = Unsafe.getUnsafe().getVolatileDouble(this, A_OFFSET);long aAsLong = Double.doubleToRawLongBits(_a);double _sum = _a + _b;long sumAsLong = Double.doubleToRawLongBits(_a);if (Unsafe.getUnsafe().compareAndSwapLong(this, A_OFFSET, aAsLong, sumAsLong))break; }兩個原子場
使用Intel TSX,您可以將硬件事務包裝在多個字段中,但是如果沒有TSX,該事務仍可以完成而無需求助于鎖。
@atomic int a = 1, b = 2;a += b * (b % 2 == 0 ? 2 : 1);如果字段在一起,仍然可以使用CAS來完成。 計劃執行CAS2操作以檢查兩個64位值。 現在,此示例將使用兩個4字節值。
assert A_OFFSET + 4 == B_OFFSET; while(true) {long _ab = Unsafe.getUnsafe().getVolatileLong(this, A_OFFSET);int _a = getLowerInt(_ab);int _b = getHigherInt(_ab);int _sum = _a + _b * (_b % 2 == 0 ? 2 : 1);int _sum_ab = setLowerIntFor(_ab, _sum);if (Unsafe.getUnsafe().compareAndSwapLong(this, A_OFFSET, _ab, _sum_ab))break; }注意:此操作可以原子方式處理a或b或兩者的更改。
原子參考
對不可變對象(例如BigDecimal)的常見用例操作。
@atomic BigDecimal a; BigDecimal b;a = a.add(b);可以在具有CompressedOops或32位JVM的系統上以這種方式實現。
BigDecimal _b = this.b; while(true) {BigDecimal _a = (BigDecimal) Unsafe.getUnsafe().getVolatileObject(this, A_OFFSET);BigDecimal _sum = _a.add(_b);if (Unsafe.getUnsafe().compareAndSwapLong(this, A_OFFSET, _a, _sum))break; }更復雜的例子
對于您的平臺,總會有一些例子過于復雜。 在帶有TSX或HotSpot支持的系統的系統上,它們可能很好,但是您需要回退。
@atomic long a, b, c, d;a = (b = (c = d + 4) + 5 ) + 6;當前不支持此功能,因為它在一個表達式中設置了多個long值。 但是,后退可能是使用現有的鎖。
synchronized(this) {a = (b = (c = d + 4) + 5 ) + 6; }結論
通過添加注釋,我們可以將原子操作添加到常規字段,而無需更改語法。 這將是對語言的自然擴展,而不會破壞向后的可比性。
翻譯自: https://www.javacodegeeks.com/2014/07/adding-atomic-operations-to-java.html
atomic java
總結
以上是生活随笔為你收集整理的atomic java_在Java中添加@atomic操作的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 什么是闪蒸 闪蒸介绍
- 下一篇: 受阅部队身高多少 看完你就知道了