成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

圖解:volatile 和原子類的異同

開發 前端
對于會被多個線程同時操作的計數器 Counter 的場景,這種場景的一個典型特點就是,它不僅僅是一個簡單的賦值操作,而是需要先讀取當前的值,然后在此基礎上進行一定的修改,再把它給賦值回去。這樣一來,我們的 volatile 就不足以保證這種情況的線程安全了。
本文轉載自微信公眾號「JerryCodes」,作者 KyleJerry 。轉載本文請聯系JerryCodes公眾號。
  • volatile和原子類
  • 原子類和 volatile 的使用場景
  • 總結

volatile和原子類

我們首先看一個案例。如圖所示,我們有兩個線程。

 

在圖中左上角可以看出,有一個公共的 boolean flag 標記位,最開始賦值為 true。

然后線程 2 會進入一個 while 循環,并且根據這個 flag 也就是標記位的值來決定是否繼續執行或著退出。

最開始由于 flag 的值是 true,所以首先會在這里執行一定時期的循環。然后假設在某一時刻,線程 1 把這個 flag 的值改為 false 了,它所希望的是,線程 2 看到這個變化后停止運行。

但是這樣做其實是有風險的,線程 2 可能并不能立刻停下來,也有可能過一段時間才會停止,甚至在最極端的情況下可能永遠都不會停止。

為了理解發生這種情況的原因,我們首先來看一下 CPU 的內存結構,這里是一個雙核的 CPU 的簡單示意圖:

 

可以看出,線程 1 和線程 2 分別在不同的 CPU 核心上運行,每一個核心都有自己的本地內存,并且在下方也有它們共享的內存。

最開始它們都可以讀取到 flag 為 true ,不過當線程 1 這個值改為 false 之后,線程 2 并不能及時看到這次修改,因為線程 2 不能直接訪問線程 1 的本地內存,這樣的問題就是一個非常典型的可見性問題。

 

要想解決這個問題,我們只需要在變量的前面加上 volatile 關鍵字修飾,只要我們加上這個關鍵字,那么每一次變量被修改的時候,其他線程對此都可見,這樣一旦線程 1 改變了這個值,那么線程 2 就可以立刻看到,因此就可以退出 while 循環了。

 

之所以加了關鍵字之后就就可以讓它擁有可見性,原因在于有了這個關鍵字之后,線程 1 的更改會被 flush 到共享內存中,然后又會被 refresh 到線程 2 的本地內存中,這樣線程 2 就能感受到這個變化了,所以 volatile 這個關鍵字最主要是用來解決可見性問題的,可以一定程度上保證線程安全。

現在讓我們回顧一下很熟悉的多線程同時進行 value++ 的場景,如圖所示:

 

如果它被初始化為每個線程都加 1000 次,最終的結果很可能不是 2000。由于 value++ 不是原子的,所以在多線程的情況下,會出現線程安全問題。但是如果我們在這里使用 volatile 關鍵字,能不能解決問題呢?

 

很遺憾,即便使用了 volatile 也是不能保證線程安全的,因為這里的問題不單單是可見性問題,還包含原子性問題。

我們有多種辦法可以解決這里的問題,第 1 種是使用synchronized 關鍵字,如圖所示:


 

 

這樣一來,兩個線程就不能同時去更改 value 的數值,保證了 value++ 語句的原子性,并且 synchronized 同樣保證了可見性,也就是說,當第 1 個線程修改了 value 值之后,第 2 個線程可以立刻看見本次修改的結果。

解決這個問題的第 2 個方法,就是使用我們的原子類,如圖所示:

 

比如用一個 AtomicInteger,然后每個線程都調用它的 incrementAndGet 方法。

在利用了原子變量之后就無需加鎖,我們可以使用它的 incrementAndGet 方法,這個操作底層由 CPU 指令保證原子性,所以即便是多個線程同時運行,也不會發生線程安全問題。

原子類和 volatile 的使用場景

我們可以看出,volatile 和原子類的使用場景是不一樣的,如果我們有一個可見性問題,那么可以使用 volatile 關鍵字,但如果我們的問題是一個組合操作,需要用同步來解決原子性問題的話,那么可以使用原子變量,而不能使用 volatile 關鍵字。

通常情況下,volatile 可以用來修飾 boolean 類型的標記位,因為對于標記位來講,直接的賦值操作本身就是具備原子性的,再加上 volatile 保證了可見性,那么就是線程安全的了。

 

總結

對于會被多個線程同時操作的計數器 Counter 的場景,這種場景的一個典型特點就是,它不僅僅是一個簡單的賦值操作,而是需要先讀取當前的值,然后在此基礎上進行一定的修改,再把它給賦值回去。這樣一來,我們的 volatile 就不足以保證這種情況的線程安全了。我們需要使用原子類來保證線程安全。

 

責任編輯:武曉燕 來源: JerryCodes
相關推薦

2020-12-11 11:11:44

原子類JavaCAS

2022-12-06 08:42:28

2022-08-17 07:53:10

Volatile關鍵字原子性

2024-08-09 08:41:14

2021-06-07 17:12:22

線程安全Atomic

2023-12-01 08:54:50

Java原子類型

2024-11-21 14:55:37

2023-12-14 07:36:16

Java并發原子類

2009-12-29 15:56:57

2024-03-15 08:18:25

volatileAtomic關鍵字

2009-12-18 15:23:03

Vista和XP路由設

2015-05-22 09:49:25

2024-08-14 18:18:47

2009-11-06 10:11:34

WCF和Web Ser

2024-01-08 09:36:47

管理庫代碼

2016-01-25 10:48:15

大數據框架HadoopSpark

2021-09-02 13:38:48

Eslint Babel 插件

2023-01-03 11:39:06

2011-04-02 13:35:21

多線程編程多線程java

2021-09-02 16:15:29

開發技能代碼
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美影院 | 亚洲精品自在在线观看 | 一区二区三区视频 | 国产原创视频 | 日本高清中文字幕 | 亚洲先锋影音 | 欧美日韩精品久久久免费观看 | 黄色一级片aaa | 激情五月综合 | 欧美v在线观看 | 亚洲黄色在线免费观看 | 亚洲第一视频网 | 久草视 | 久久a久久| 亚洲三区在线观看 | 人妖videosex高潮另类 | 国产日韩欧美 | 久久久久久久久国产成人免费 | 久久一区精品 | 日韩中文字幕视频在线 | 日韩在线一区二区 | 日韩小视频 | 亚洲精品成人在线 | 久久一区精品 | 国产在线精品一区二区三区 | 色橹橹欧美在线观看视频高清 | 免费观看一级毛片 | 日本a视频 | 中文字幕一区二区三区四区不卡 | 在线黄色影院 | 夜夜草天天草 | 国产日韩欧美激情 | 久久www免费视频 | 久久久久久国产精品 | 91精品国产777在线观看 | 精品成人佐山爱一区二区 | 成人国产精品久久 | 久久久一区二区三区 | 天天拍天天草 | 成人三级影院 | 男人的天堂亚洲 |