前言:
因為最近剛學習執行緒相關的知識,所以想在此做一下筆記,順帶借此機會說一下自己對于相關知識的 理解以供參考;如在本文中發現有任何不妥的地方,請在評論區評論或與作者聯系,以供修正;最后希望能在csdn這個平臺與大家一起學習,共同進步,
正文:
關于執行緒之間為什么是不可見的,談到這個問題時我覺得有必要先了解一下執行緒執行時的一個記憶體空間;在Java中每一個的執行緒都有一塊獨立的記憶體空間,俗稱執行緒作業區,當它們去執行臨界區的資源(共享資源)時,都會先去主記憶體將共享資源復制一份到自己的作業記憶體中再進行操作,最后再把操作完的副本寫入到主記憶體中;看似表面上是直接操作了共享資源,其實實際上是操作了共享資源的副本;
為了方便理解我畫了流程圖,如下:
執行緒記憶體之間的關系圖:
執行緒運行時的具體流程:
回到正題,相信看到這里不少的小伙伴對于執行緒不可見的問題在心里應該都有一個答案了;不過為了方便更多人的理解我還是闡述下致因吧;因為執行緒每次執行時都是要先拿取資源的副本,再在自己的作業記憶體里進行操作,最后再寫入到主記憶體資源中;那這時容易出現一種情況,例如當多個執行緒要修改同一資源時,一個執行緒優先去復制了資源在自己記憶體進行操作時,突然某一執行緒趁機也偷偷的把資源復制到自己作業記憶體中操作,這時原先的那個先執行的執行緒執行完了操作把副本內容寫入了主記憶體中時,偷偷摸摸的那個執行緒也跟著執行完了把結果寫入到了主記憶體后,最后導致將原先執行的執行緒寫入的結果給覆寫了,在這種情況下時我們就可以稱之為執行緒之間的不可見,
同樣為了方便大家理解也畫了一個流程圖(注意序號):

為了方便大家更加深入的理解,以下文章還會通過a++這串代碼來進行詮釋:
總所周知a++是一個執行緒不安全的操作,那到底它不安全在哪里呢?為什么會出現這樣的問題呢?讓我們一起來解開這些疑問,
其實導致這個問題的原因正是我們之前說的執行緒之間的可見性問題,這時可能有的人就會問了,“誒,這不就只有一串代碼嗎?怎么會出現這樣的問題呢(黑人問號臉)???”別急,接下來才是我們的重頭戲,我們的java在執行這串代碼的時候底層是通過多串指令來達成這個操作,拆解后分別是:先拿到變數a的值---再給a進行+1操作-----最后把得出的結果賦值給變數a;
這是a++操作通過位元組碼反編譯出來的指令(有興趣的可以去了解下javap)

通過上圖就可以看到a++是由多段指令來完成的,再聯系上文就清楚它為什么是執行緒不安全的操作了,
那么遇見這種問題時有沒有什么解決辦法?從我個人考慮的話解決的辦法有兩個,一個是鎖機制,另一個是volatile關鍵字,如果各位有興趣的話可以在下方評論,我會另外挑時間講解下鎖機制和volatile關鍵字,當然如果有其他的解決方法歡迎進行補充,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/355248.html
標籤:其他
上一篇:一次實戰程序的漏洞挖掘
