volatile關鍵字和AtomicInteger

在Java中,線程部分是一個重點,本篇文章說的JUC也是關于線程的。JUC就是java.util .concurrent工具包的簡稱。這是一個處理線程的工具包,JDK 1.5開始出現的。下面一起來看看它怎么使用。

一、volatile關鍵字與內存可見性

1、內存可見性:
先來看看下面的一段代碼:

?

?

?

?

?

上圖中這段代碼很簡單,就是一個ThreadDemo類繼承Runnable創建一個線程。它有一個成員變量flag為false,然后重寫run方法,在run方法里面將flag改為true,同時還有一條輸出語句。然后就是main方法主線程去讀取flag。如果flag為true,就會break掉while循環,否則就是死循環。按道理,下面那個線程將flag改為true了,主線程讀取到的應該也是true,循環應該會結束。運行結果

?

從上圖中可以看到,該程序并沒有結束,也就是死循環。說明主線程讀取到的flag還是false,可是另一個線程明明將flag改為true了,而且打印出來了,這是什么原因呢?這就是內存可見性問題。

  • 內存可見性問題:當多個線程操作共享數據時,彼此不可見。



要解決這個問題,可以加鎖。如下:

加了鎖,就可以讓while循環每次都從主存中去讀取數據,這樣就能讀取到true了。但是一加鎖,每次只能有一個線程訪問,當一個線程持有鎖時,其他的就會阻塞,效率就非常低了。不想加鎖,又要解決內存可見性問題,那么就可以使用volatile關鍵字。

?

2、volatile關鍵字:

  • 用法:

volatile關鍵字:當多個線程操作共享數據時,可以保證內存中的數據可見。用這個關鍵字修飾共享數據,就會及時的把線程緩存中的數據刷新到主存中去,也可以理解為,就是直接操作主存中的數據。所以在不使用鎖的情況下,可以使用volatile。如下:


這樣就可以解決內存可見性問題了。

  • volatile和synchronized的區別:
    volatile不具備互斥性(當一個線程持有鎖時,其他線程進不來,這就是互斥性)。
    volatile不具備原子性。

?

?

二、原子性

1、理解原子性:
上面說到volatile不具備原子性,那么原子性到底是什么呢?先看如下代碼:

?

?

這段代碼就是在run方法里面讓i++,然后啟動十個線程去訪問。看看結果:

?

?

可以發現,出現了重復數據。明顯產生了多線程安全問題,或者說原子性問題。所謂原子性就是操作不可再細分,而i++操作分為讀改寫三步,如下:

?

所以i++明顯不是原子操作。上面10個線程進行i++時,內存圖解如下:

?

看到這里,好像和上面的內存可見性問題一樣。是不是加個volatile關鍵字就可以了呢?其實不是的,因為加了volatile,只是相當于所有線程都是在主存中操作數據而已,但是不具備互斥性。比如兩個線程同時讀取主存中的0,然后又同時自增,同時寫入主存,結果還是會出現重復數據。

2、原子變量:
JDK 1.5之后,Java提供了原子變量,在java.util.concurrent.atomic包下。原子變量具備如下特點:

  • 有volatile保證內存可見性。
  • 用CAS算法保證原子性。

3、CAS算法:
CAS算法是計算機硬件對并發操作共享數據的支持,CAS包含3個操作數:

  • 內存值V
  • 預估值A
  • 更新值B

當且僅當V==B時,才會把B的值賦給V,即V = B,否則不做任何操作。就上面的i++問題,CAS算法是這樣處理的:首先V是主存中的值0,然后預估值A也是0,因為此時還沒有任何操作,這時V=B,所以進行自增,同時把主存中的值變為1。如果第二個線程讀取到主存中的還是0也沒關系,因為此時預估值已經變成1,V不等于B,所以不進行任何操作。

4、使用原子變量改進i++問題:

?

  • 定義:AtomicInteger是一個提供原子操作的Integer類,通過線程安全的方式操作加減。
  • 使用場景?:適合高并發情況下的使用

    AtomicInteger是在使用非阻塞算法實現并發控制,在一些高并發程序中非常適合,但并不能每一種場景都適合,不同場景要使用使用不同的數值類。

    注意:高并發的情況下,i++無法保證原子性,往往會出現問題,所以引入AtomicInteger


原子變量用法和包裝類差不多,如下:

?

?

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/271831.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/271831.shtml
英文地址,請注明出處:http://en.pswp.cn/news/271831.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

前端:JS幾種常見的排序

??作者主頁:IT技術分享社區 ??作者簡介:大家好,我是IT技術分享社區的博主,從事C#、Java開發九年,對數據庫、C#、Java、前端、運維、電腦技巧等經驗豐富。 ??個人榮譽: 數據庫領域優質創作者🏆&#x…

bzoj3747 [POI2015]Kinoman

線段樹&#xff0c;記錄next[i]下一部與當前電影一樣的位置&#xff0c;然后枚舉區間左端點i&#xff0c;詢問線段樹最大值后刪除i到next[i-1]這段區間的觀影值&#xff0c;且增加next[i]到next[next[i]]-1這段區間的觀影值。 代碼&#xff0c;跑的有點慢 1 #include<cstdio…

java_poi教程.pdf,如何使用POI轉換.DOC / .DOCX為PDF在Java ..?

how to convert ms-document to PDF, is there any example pls sharewith me.. thanks.解決方案If you are requiered to use POI i guess you should take a look at org.apache.poi.hwpf.converterI never tried this, but i guess its worth a try atleast.It seems like y…

在線語音轉文字工具V1.0

在線語音轉文字工具V1.0介紹在線語音轉文字工具V1.0&#xff0c;采用C#開發語音基于Framework4.5開發&#xff0c;主要采用百度語音識別SDK&#xff0c;實現了在線文本轉語音的功能&#xff0c;可以轉換后直接播放。有需要的朋友可以下載學習一下。如果遇到問題的可以留言或者私…

超媒體

“超媒體”是超級媒體的縮寫。超媒體是一種采用非線性網狀結構對塊狀多媒體信息&#xff08;包括文本、圖像、視頻等&#xff09;進行組織和管理的技術。 超媒體在本質上和超文本是一樣的&#xff0c;只不過超文本技術在誕生的初期管理的對象是純文本&#xff0c;所以叫做超文本…

java局部刷新session過期_Ajax局部頁面刷新和History API結合的陷阱

ajax在現代網站已經得到非常普遍地應用&#xff0c;主要的好處大家都知道(異步加載數據&#xff0c;不用刷新整個瀏覽器&#xff0c;更小的數據傳輸尺寸)。對于那些老網站或者老項目來說全盤改造成ajax并不現實&#xff0c;于是就有了“局部頁面刷新”這個解決方案。如果不知道…

Java通過Netty,實現Websocket消息推送只需要簡單幾步

前言 曾幾何時&#xff0c;不知道大家有沒有在項目里遇到過需要服務端給客戶端推送消息的需求&#xff0c;是否曾經苦惱過、糾結過&#xff0c;我們知道要想實現這樣的需求肯定離不開websocket長連接方式&#xff0c;那么到底是該選原生的websocket還是更加高級的netty框架呢&a…

53.Maximum Subarray

/** 53.Maximum Subarray * 2016-5-7 by Mingyang * 如果我們從頭遍歷這個數組。對于數組中的其中一個元素&#xff0c;它只有兩個選擇&#xff1a; 1.* 要么加入之前的數組加和之中&#xff08;跟別人一組&#xff09; * 2. 要么自己單立一個數組&#xff08;自己單開一組&…

java 創建者設計模式_Java設計模式之創建者模式分享熱愛編程,程序人生

PS:今天的23中設計模式中的創建者方式&#xff0c;至此告一段落。我今天帶來的技術分享為創建者模式以及原型模式。當然在Java中這兩種方式很常見&#xff0c;只不過我們寫的次數確實有點低而已&#xff0c;但是這不是我不學它的借口&#xff01;&#xff01;&#xff01;創建者…

一文讀懂電感器的原理、結構、作用及分類

電感器是能夠把電能轉化為磁能而存儲起來的元件。電感器的結構類似于變壓器&#xff0c;但只有一個繞組。電感器具有一定的電感&#xff0c;它只阻礙電流的變化。 如果電感器在沒有電流通過的狀態下&#xff0c;電路接通時它將試圖阻礙電流流過它&#xff1b;如果電感器在有電流…

final關鍵字與static對比

final關鍵字與static對比 static關鍵字修飾變量時&#xff0c;會使該變量在類加載時就會被初始化&#xff0c;不會因為對象的創建再次被加載&#xff0c;當變量被static 修飾時就代表該變量只會被初始化一次 例如圖中所示&#xff0c;被static修飾的變量j&#xff0c;雖然創建…

juce中的BailOutChecker

界面庫中值得注意的一點就是對象響應事件的時候自身被刪除了&#xff0c;那么后續的訪問自然就會出問題&#xff0c;所以需要在響應事件之后先添加引用&#xff0c;相關處理之后再查看自身是否已經被刪除&#xff0c;如果已經被刪除那么就直接退出。juce中通過BailOutChecker來…

java quartz 跳過_Java Quartz計劃作業-禁止同時執行作業

我正在使用Quartz Job執行特定任務。我也在我的Main應用程序類中安排它的執行&#xff0c;而我試圖完成的工作是不允許同時執行此作業的實例。因此&#xff0c;調度程序僅應在其先前實例完成后才執行作業。這是我的工作班級&#xff1a;public class MainJob implements Job {s…

mac USB串口工具配置

安裝USB serial 驅動 我的usb serial芯片是 pl2303, 先到官網上下載對應驅動&#xff0c;并安裝。安裝完成之后會要求重啟。 http://www.prolific.com.tw/admin/Technology/GetFile.ashx?fileID238 安裝 minicom https://alioth.debian.org/projects/minicom/ 下載源碼&…

macpro生成公鑰并查看公鑰

打開macpro的終端輸入以下命令&#xff1a; $ cd ~/.ssh $ ls 此時發現沒有那個id_rsa.pub文件&#xff0c;沒有&#xff0c;就需要創建公鑰 用ssh-keygen創建公鑰 此時已經有了

java join 源碼_join on 和where 一起使用的細節

left join :左連接&#xff0c;返回左表中所有的記錄以及右表中連接字段相等的記錄。right join :右連接&#xff0c;返回右表中所有的記錄以及左表中連接字段相等的記錄。inner join: 內連接&#xff0c;又叫等值連接&#xff0c;只返回兩個表中連接字段相等的行。full join:外…

SSIS 學習之旅 FTP訪問類

這章把腳本任務訪問FTP的方法 全部給大家。 控件的使用大家如果有不懂得可以看下我之前的文章。第一章&#xff1a;SSIS 學習之旅 第一個SSIS 示例&#xff08;一&#xff09;&#xff08;上&#xff09; 第二章&#xff1a;SSIS 學習之旅 第一個SSIS 示例&#xff08;二&#…

Spring Cloud Feign 使用Apache的HTTP Client替換Feign原生httpclient

http 連接池能提升性能 http 的背景原理 a. 兩臺服務器建立 http 連接的過程是很復雜的一個過程&#xff0c;涉及到多個數據包的交換&#xff0c;并且也很耗時間。 b. Http 連接需要的 3 次握手 4 次分手開銷很大&#xff0c;這一開銷對于大量的比較小的 http 消息來說更大。…