摘要:否則它就會用新的值替代當前值。在這種情況下,鎖可能會優于原子變量,但在實際的爭用級別中,原子變量的性能優于鎖。在中引入了另外一個構件。
題目要求
在我們深入了解CAS(Compare And Swap)策略以及它是如何在AtomicInteger這樣的原子構造器中使用的,首先來看一下這段代碼:
public class MyApp { private volatile int count = 0; public void upateVisitors() { ++count; //increment the visitors count } }
這里的代碼記錄的訪問應用的訪客的數量。這段代碼有問題么?如果多個線程試圖更新這個數值會發生什么?事實上,這里的問題在于單單將count標記為volatile并不能保證原子性,++count也不是一個原子操作。想要了解更多請查看這里。
那么如果我們將方法標記為synchronized可以解決這個問題嗎?
public class MyApp { private int count = 0; public synchronized void upateVisitors() { ++count; //increment the visitors count } }
這段代碼可以保證原子性嗎?可以。
這段代碼可以保證可見性啊?可以。
那這里還有什么問題?
它使用了鎖從而引入了大量的延時和。詳情查看這里。這種方式開銷太大。
為了解決這個問題引入了原子構造器。如果我們使用AtomicInteger來記錄訪問量,也可以達到目的。
public class MyApp { private AtomicInteger count = new AtomicInteger(0); public void upateVisitors() { count.incrementAndGet(); //increment the visitors count } }
支持原子操作的類如AtomicInteger,使用CAS來實現。CAS并沒有使用鎖,而是以一種很樂觀的方式來處理。它遵循以下幾步:
比較原始的值和我們已經獲得的值
如果這兩個值不同,說明中間有線程改變了值。否則它就會用新的值替代當前值。
看一下AtomicLong類中的代碼:
public final long incrementAndGet() { for (;;) { long current = get(); long next = current + 1; if (compareAndSet(current, next)) return next; } }
在JDK 8中上面的代碼被更改為一行代碼:
public final long incrementAndGet() { return unsafe.getAndAddLong(this, valueOffset, 1L) + 1L; }
這一行代碼有何優點?
實際上,這一行是會由JIT翻譯為優化的指令序列的JVM內部函數。在x86架構中它就是一條CPU指令LOCK XADD,會比CAS循環的性能好很多。
現在考慮一下當我們有較高的爭用以及一些線程想要更??新相同的原子變量的可能性。在這種情況下,鎖可能會優于原子變量,但在實際的爭用級別中,原子變量的性能優于鎖。在Java 8 中引入了另外一個構件LongAdder。
LongAdder并不完全是AtomicLong的替代品,我們需要考慮以下因素:
當沒有爭用時,AtomicLong性能更好
LongAdder將分配Cells(在抽象類Striped64中聲明的final類)以避免消耗內存的爭用。所以如果我們有一個緊張的內存預算,我們應該更傾向于使用AtomicLong。
想要了解更多開發技術,面試教程以及互聯網公司內推,歡迎關注我的微信公眾號!將會不定期的發放福利哦~
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/68794.html
摘要:簡介從創建以來,就支持核心的并發概念如線程和鎖。這篇文章會幫助從事多線程編程的開發人員理解核心的并發概念以及如何使用它們。請求操作系統互斥,并讓操作系統調度程序處理線程停放和喚醒。 簡介 從創建以來,JAVA就支持核心的并發概念如線程和鎖。這篇文章會幫助從事多線程編程的JAVA開發人員理解核心的并發概念以及如何使用它們。 (博主將在其中加上自己的理解以及自己想出的例子作為補充) 概念 ...
摘要:算法算法會先對一個內存變量位置和一個給定的值進行比較,如果相等,則用一個新值去修改這個內存變量位置。因為是非公平鎖,所以一上來就嘗試搶占鎖給定舊值并希望用新值去更新內存變量。 本文翻譯和原創各占一半,所以還是厚顏無恥歸類到原創好了...https://howtodoinjava.com/jav...java 5 其中一個令人振奮的改進是新增了支持原子操作的類型,例如 AtomicInt...
摘要:有可能一個線程中的動作相對于另一個線程出現亂序。當實際輸出取決于線程交錯的結果時,這種情況被稱為競爭條件。這里的問題在于代碼塊不是原子性的,而且實例的變化對別的線程不可見。這種不能同時在多個線程上執行的部分被稱為關鍵部分。 為什么要額外寫一篇文章來研究volatile呢?是因為這可能是并發中最令人困惑以及最被誤解的結構。我看過不少解釋volatile的博客,但是大多數要么不完整,要么難...
摘要:什么是仿射變換一組設備無關的坐標被用來將所有的坐標信息傳遞給對象。對象作為對象狀態的一部分。類代表一個的仿射變化,將一組的坐標進行線性映射到另一組保留了平行關系和豎直關系的坐標中。 什么是仿射變換 一組設備無關的坐標被用來將所有的坐標信息傳遞給Graphics2D對象。AffineTransform對象作為Graphics2D對象狀態的一部分。該對象定義了如何將用戶空間的坐標轉化為設備...
摘要:本文簡介類概覽類構造器總結類構造方法類使用舉例類概覽是一個實現了接口,并且鍵為型的哈希表。中的條目不再被正常使用時,會被自動刪除。它的鍵值均支持。和絕大多數的集合類一樣,這個類不是同步的。 本文簡介 WeakHashMap類概覽 WeakHashMap類構造器總結 WeakHashMap類構造方法 WeakHasjMap類使用舉例 1. WeakHashMap類概覽 Wea...
閱讀 940·2021-09-27 13:36
閱讀 888·2021-09-08 09:35
閱讀 1064·2021-08-12 13:25
閱讀 1437·2019-08-29 16:52
閱讀 2907·2019-08-29 15:12
閱讀 2726·2019-08-29 14:17
閱讀 2606·2019-08-26 13:57
閱讀 1012·2019-08-26 13:51