日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

并发模型之——共享内存模型(线程与锁)理论篇

發(fā)布時(shí)間:2024/7/19 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 并发模型之——共享内存模型(线程与锁)理论篇 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

? ? ? 這里我們使用Java的線程與鎖來(lái)解析共享內(nèi)存模型;做過(guò)java開(kāi)發(fā)并且了解線程安全問(wèn)題的知道,要使某段代碼是線程安全的那必須要滿足兩個(gè)條件:內(nèi)存可見(jiàn)性、原子性
內(nèi)存可見(jiàn)性
? ? ? 在JVM規(guī)定多個(gè)線程進(jìn)行通訊是通過(guò)共享變量進(jìn)行的,而Java內(nèi)存模型規(guī)定了有主內(nèi)存是所有線程共享的,而各個(gè)線程又有自己的工作內(nèi)存,線程只能訪問(wèn)自己的工作內(nèi)存中數(shù)據(jù);
? ? ? 如:有一個(gè)共享變量x,兩個(gè)線程a、b變量x存儲(chǔ)在主內(nèi)存中然后又兩個(gè)x的拷貝分別存儲(chǔ)在a、b線程的工作內(nèi)存中線程a、b只能對(duì)自己工作內(nèi)存中的x的拷貝進(jìn)行操作,不可直接操作主內(nèi)存;
? ? ? 線程a對(duì)x修改時(shí)先把值放到自己的工作內(nèi)存中,然后再把工作內(nèi)存中的x拷貝更新到主內(nèi)存中,線程b同樣如此;當(dāng)線程a更新了主內(nèi)存后線程b刷新工作內(nèi)存后就能看到a更新后的最新值這就是內(nèi)存可見(jiàn)性問(wèn)題;
? ? ? 內(nèi)存可見(jiàn)性要保證兩點(diǎn):1、線程修改后的共享變量更新到主內(nèi)存;2、從主內(nèi)存中更新最新值到工作內(nèi)存中;
? ? ? 內(nèi)存可見(jiàn)性:線程對(duì)共享變量的修改其他線程可以看到修改后的值;

? ?
原子性
? ? ? 當(dāng)線程引用共享變量時(shí),工作內(nèi)存中沒(méi)有共享變量時(shí)它會(huì)從主內(nèi)存復(fù)制共享變量到自己工作內(nèi)存中,當(dāng)工作內(nèi)存有共享變量時(shí)線程可能會(huì)從主內(nèi)存更新也有可能直接使用工作內(nèi)存中的共享變量;
有代碼塊,count為共享變量:

1 ++count;

// count初始值為0,這時(shí)有a、b線程都執(zhí)行這行代碼,可能有不少人以為線程a , b執(zhí)行完成后count的值為2,但真實(shí)情況是count最終值可能為1也可能為2,因?yàn)檫@里有一個(gè)原子性問(wèn)題;

? ? ?熟悉Java的都知道在Java中++count非原子操作,流程為:
? ? ? ? ? ?1、把主內(nèi)存共享變量count拷貝到工作內(nèi)存
? ? ? ? ? ?2、把工作內(nèi)存中count值+1
? ? ? ? ? ?3、把結(jié)果寫(xiě)回更新回主內(nèi)存
? ? ?當(dāng)只有一個(gè)線程時(shí)這個(gè)操作沒(méi)有問(wèn)題;
? ? ?當(dāng)有多個(gè)線程時(shí)有可能出現(xiàn):
? ? ? ? ? ?1、 線程a把主內(nèi)存共享變量count拷貝到工作內(nèi)存
? ? ? ? ? ?2、 線程b把主內(nèi)存共享變量count拷貝到工作內(nèi)存
? ? ? ? ? ?3、 線程a把工作內(nèi)存中count進(jìn)行+1
? ? ? ? ? ?4、 線程b把工作內(nèi)存中count進(jìn)行+1
? ? ? ? ? ?5、 線程a把工作內(nèi)存更新到主內(nèi)存
? ? ? ? ? ?6、 線程b把工作內(nèi)存更新到主內(nèi)存
? ? ? a,b線程執(zhí)行完后最終count的值只是1而不是我們期望得到的2,因?yàn)檫@里出現(xiàn)了多個(gè)線程交叉執(zhí)行導(dǎo)致破壞了程序的有序性,而且count+1操作又不是原子的,所以我們必須要保證這程序的原子性,可以使用Java中的synchronized(同步)或Lock機(jī)制來(lái)解決;

? ? ? 使用共享內(nèi)存模型進(jìn)行并發(fā)編程時(shí)必須要解決我們上面介紹的兩個(gè)點(diǎn):內(nèi)存可見(jiàn)性、原子性,但現(xiàn)在大部分編程語(yǔ)言原生都支持共享內(nèi)存模型方式的并發(fā)所以我們很容易就可以達(dá)到這兩個(gè)要求;
? ? ? 現(xiàn)在代碼的執(zhí)行要經(jīng)過(guò)多層的優(yōu)化對(duì)指令重排序,如:編譯器、處理器等級(jí)別的優(yōu)化,經(jīng)過(guò)這些優(yōu)化重排序后最終代碼執(zhí)行順序可能與之前是不一致的,在單線程時(shí)中編譯器、處理會(huì)保持as-if-serial,對(duì)不存在數(shù)據(jù)依賴(lài)的進(jìn)行重排序,所以不會(huì)出現(xiàn)重排序問(wèn)題;但在多線程情況下就會(huì)出現(xiàn)問(wèn)題,不過(guò)還好Java中有些機(jī)制可以使程序在編譯器、處理器優(yōu)化時(shí)會(huì)對(duì)有數(shù)據(jù)依賴(lài)的禁止指令重排序,如:volatile、synchronized等,所以我們可以很輕松應(yīng)對(duì)這問(wèn)題;

?

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 指令重排序問(wèn)題
? ? ? 在Java中我們要使代碼在多線程中同時(shí)滿足內(nèi)存可見(jiàn)性與有序性那就要使用Java提供給我們的同步與鎖機(jī)制如:synchronized、volatile、Lock、concurrent類(lèi)等;
? ? ? 優(yōu)點(diǎn):共享內(nèi)存模型(線程與鎖)可以說(shuō)是最常見(jiàn)的并發(fā)模型大多數(shù)編程語(yǔ)言都原生支持,也適合解決很多問(wèn)題,通過(guò)線程與鎖實(shí)現(xiàn)起來(lái)相對(duì)也簡(jiǎn)單點(diǎn);
? ? ? 缺點(diǎn):通過(guò)多線程實(shí)現(xiàn)并發(fā),而線程耗費(fèi)的資源比較多,線程總數(shù)有限制;通過(guò)共享內(nèi)存來(lái)實(shí)現(xiàn)多線程通訊又會(huì)涉及到鎖、竟態(tài)、死鎖等問(wèn)題影響程序性能;一不小心就會(huì)陷入可見(jiàn)性問(wèn)題、重排序問(wèn)題等而且多線程程序不容易測(cè)試、維護(hù)等;

?

?文章首發(fā)地址:Solinx
http://www.solinx.co/archives/179

轉(zhuǎn)載于:https://www.cnblogs.com/softlin/p/4474838.html

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

總結(jié)

以上是生活随笔為你收集整理的并发模型之——共享内存模型(线程与锁)理论篇的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。