多個執行緒可以讀一個變數,只有一個執行緒可以對這個變數進行寫,到底要不要加鎖?豬fans2020-06-24 19:26:25

其實我認為加鎖的意義也不大。為什麼呢,假如加了鎖,在寫的時候如果有讀的執行緒,那麼需要等待讀完再寫,這時候,這個讀的資料也是寫之前的資料。假設不加鎖,還是讀執行緒先,寫執行緒後執行,這時候很有可能寫會跑到讀的前面優先執行寫的操作。讀的就會是新資料。否則,讀的就是老資料。大多數場景是可以這樣做的。當然,如果資料的時間先後很敏感的,肯定要加鎖

多個執行緒可以讀一個變數,只有一個執行緒可以對這個變數進行寫,到底要不要加鎖?架構思維2020-06-26 12:18:17

先說結論:

不必要

如果不需要可見性,什麼都不需要加

如果需要保證可見性,則需要加volatile關鍵字。這裡可以加鎖,但是沒必要,對效能有影響

下面簡單解釋下原因:

加鎖是因為操作不是原子性的,以i++這個操作來解釋,看下面兩張圖。

多個執行緒可以讀一個變數,只有一個執行緒可以對這個變數進行寫,到底要不要加鎖?

多個執行緒可以讀一個變數,只有一個執行緒可以對這個變數進行寫,到底要不要加鎖?

i++這個操作需要

先將i的值從記憶體中讀出來

然後加1

最後寫回去

看上面第二張圖,能很清楚的理解流程吧?

加鎖就是保證上面的三步是一個原子操作。

回到問題,這裡只有一個執行緒寫,實際沒有競爭,所以沒必要加鎖。

但是,看第一張圖,因為有主記憶體和本地記憶體的存在

執行緒先寫入本地記憶體

然後刷入主記憶體

其它記憶體同步主記憶體到工作記憶體

然後從工作記憶體中讀取

一個執行緒寫入後,不能保證其它執行緒立即看到,這就是可見性問題。

加了volatile關鍵字後,會強制操作後同步工作記憶體和主記憶體,保證其它執行緒立刻看到。

多個執行緒可以讀一個變數,只有一個執行緒可以對這個變數進行寫,到底要不要加鎖?java架構設計2020-06-25 21:56:42

要加鎖!我們需要保證的是該變數在多執行緒環境下是執行緒安全的。

典型的read write lock場景,Java中比較經典的

ReentrantReadWriteLock。

另外多說一句,當你不確定要不要加鎖的時候,就是你需要加鎖的時候。

然後你參考MySQL資料庫下Innodb儲存引擎預設級別是RR,防止

髒讀

,即當我們update一條資料的時候,是加了行鎖的,其他的讀執行緒在等待著,所以你需不需要加鎖?

不加鎖會出現什麼問題?

顯然會出現髒讀的問題!

這也是面試中常見的一種問題,以該題為突破口,帶你進入多執行緒的世界。

其實加鎖也很簡單,Java中對該變數進行volatile修飾即可!

不瞭解volatile的同學需要學習了,本質上是為了保證變數操作時候的

記憶體可見性

那怎麼保證記憶體可見性呢?

禁止指令重排序、記憶體屏障。

重點看下圖hotspot虛擬機器的實現:

多個執行緒可以讀一個變數,只有一個執行緒可以對這個變數進行寫,到底要不要加鎖?

當我們對一個變數i進行volatile修飾後,Java在位元組碼層面是對這個變數進行了

ACC_COLATILE

標記。當我們的JVM虛擬機器看見

ACC_COLATILE

這個位元組碼指令後就會對這個變數加一個lock指令(cpu層面的),還是一個

的概念。

有的人說考慮程式的吞吐量,在保證最終一致性的前提下可以不加鎖,那我的理解就是你不是在搞事情就是在埋坑,埋一個還不容易被發現的坑。這種坑測試測不出來,線上出問題了還復現不出來,所以為了安全還是加鎖吧~

多個執行緒可以讀一個變數,只有一個執行緒可以對這個變數進行寫,到底要不要加鎖?沉思的狗2020-06-25 07:40:52

如果僅僅是你描述的,那不需要加鎖。

如果需要每次讀取最新值,注意加volatile。

如果需要及時拿到最新值,注意使用執行緒通知手段。

多個執行緒可以讀一個變數,只有一個執行緒可以對這個變數進行寫,到底要不要加鎖?書城路45332020-06-24 16:42:08

看你的需求了,如果你不怕丟資料,或者讀到過期的資料,就不用加鎖,如果你對資料的要求很嚴格的話,那還是要加鎖的

多個執行緒可以讀一個變數,只有一個執行緒可以對這個變數進行寫,到底要不要加鎖?_九月授衣_2020-06-24 19:39:30

這跟多少個執行緒讀有啥關係,就算是一個執行緒讀,也是讀寫併發呀。至於要不要加鎖,看業務是不是需要嚴格的資料一致性或者合法性。

多個執行緒可以讀一個變數,只有一個執行緒可以對這個變數進行寫,到底要不要加鎖?mq302020-11-17 02:49:47

其實,樓主需要再明確具體化點你的需求。這裡面主要涉及兩個點需要考慮的,一是執行緒互斥,二是執行緒同步。為什麼需要互斥,保護共享的資源。如題所述題中的變數就在多個執行緒共享。場景一:只有一個執行緒可以寫,這種情況下,原子操作也能保證資料一致性,但使用鎖也可以,只是耗點效能。場景二:是否需要控制必須先寫後才能讀,沒有寫操作就等待,等待寫完成後就讀取。如果是,這裡需要考慮執行緒同步,可以考慮使用條件變數,以達到控制執行緒同步。

多個執行緒可以讀一個變數,只有一個執行緒可以對這個變數進行寫,到底要不要加鎖?熟悉的陌生人08192020-09-04 09:17:10

原則上不用,但是(敲重點):如果這個專案只是你一人的,並且你永遠對它內部邏輯非常清楚,不會因為修改增加邏輯去多個執行緒寫這個變數就不用加鎖,反之這如果是個團隊專案,並且專案邏輯擴充套件會越來越複雜,並且團隊間專案交接交叉頻繁,文件不清,新上手的人不清楚邏輯就會可能對這個變數擴充套件寫邏輯,這種情況就要用鎖,這是要解決專案維護和擴充套件問題,現在n多專案都存在多次交接和擴充套件後混亂問題。

多個執行緒可以讀一個變數,只有一個執行緒可以對這個變數進行寫,到底要不要加鎖?半瓶水vlog2020-06-24 21:09:02

要看變數型別,如果是原子級的,哪就沒問題,不用鎖

多個執行緒可以讀一個變數,只有一個執行緒可以對這個變數進行寫,到底要不要加鎖?計算理論2020-06-25 22:45:30

Java中該變數用volatile約束,因Java每個執行緒都會將用到的變數copy到現成工作棧中,而修改了記憶體中變數的值,還需要將此值由執行緒工作棧寫入到記憶體對應區域,因為這些資料讀寫操作要多個步驟完成,因此不具有原子性,故需要指定volatile關鍵字修飾變數,讓執行緒對此變數的操作都直接操作記憶體,而不是有中間的對於執行緒棧的複製動作。

多個執行緒可以讀一個變數,只有一個執行緒可以對這個變數進行寫,到底要不要加鎖?點顆煙喝口水2020-06-25 02:07:46

原則上要加鎖。個別簡單場景可以不加,比如可以確定讀寫不會衝突,或者單個簡單控制變數考慮volatile。如果是大專案且效能最佳化指標不是納秒級的,建議加上鎖,免得埋坑。

多個執行緒可以讀一個變數,只有一個執行緒可以對這個變數進行寫,到底要不要加鎖?Drizzle丶vivi2020-06-25 08:43:58

java有讀寫鎖,寫鎖互斥

多個執行緒可以讀一個變數,只有一個執行緒可以對這個變數進行寫,到底要不要加鎖?lealee2020-06-25 19:35:32

看設計,看需求。一般讀寫鎖,讀讀共享,讀寫互斥,寫寫互斥。

多個執行緒可以讀一個變數,只有一個執行緒可以對這個變數進行寫,到底要不要加鎖?北京南城日記2021-04-24 08:18:42

看變數型別,以32位系統為例,不大於32bit的變數沒有問題,1原子操作,2讀寫匯流排競爭和仲裁

多個執行緒可以讀一個變數,只有一個執行緒可以對這個變數進行寫,到底要不要加鎖?沙漠海1794703152020-06-26 22:12:21

技術上不懂

處理上 寫變數的執行緒正在寫的時候 應當不讓讀變數才行?這個環節是要加鎖的

多個執行緒可以讀一個變數,只有一個執行緒可以對這個變數進行寫,到底要不要加鎖?愛看動漫的老臘肉2020-06-25 00:43:18

多讀一寫,我贊同峰子777的做法,原因:從可見性來說,用volatile修飾能保證其他執行緒讀到的是最新值

多個執行緒可以讀一個變數,只有一個執行緒可以對這個變數進行寫,到底要不要加鎖?江東-chenhu2020-06-25 08:59:07

看你用什麼語言開發的,如果是c/C++,假設讀寫int, int記憶體裡是4Byte,則有可能

寫執行緒寫到2byte,就有一個讀執行緒讀取資料了,則是就是髒資料了。

但一些高階語言,對變數操作基本是原子操作,基本是原子操作。

多個執行緒可以讀一個變數,只有一個執行緒可以對這個變數進行寫,到底要不要加鎖?老成Mrcheng2020-06-25 08:53:56

寫的前後要給變數加鎖啊,而且這樣的場景有專業術語的叫樂觀鎖。

樂觀鎖(寫的前後不能讀),悲觀鎖(讀的前後不能寫)

比如,一場足球比賽,足球的位置是個固定的變數v,張三踢一腳,把球從a踢到b,如果不鎖,所有人收到球的位置可能是a也可能是b,如果寫v的時候鎖上讀的操作,那麼就不會出現誤讀的情況。

多個執行緒可以讀一個變數,只有一個執行緒可以對這個變數進行寫,到底要不要加鎖?sanix2020-06-25 02:48:58

不要加鎖,但是要鎖匯流排,加lock字首

多個執行緒可以讀一個變數,只有一個執行緒可以對這個變數進行寫,到底要不要加鎖?金聖嘆加加2020-11-17 08:58:24

加或不加 看情況