多線程的目的

為什么要使用多線程?可以簡(jiǎn)單的分兩個(gè)方面來(lái)說(shuō):

  • 在多個(gè)cpu核心下,多線程的好處是顯而易見(jiàn)的,不然多個(gè)cpu核心只跑一個(gè)線程其他的核心就都浪費(fèi)了;

  • 即便不考慮多核心,在單核下,多線程也是有意義的,因?yàn)樵谝恍┎僮?,比如IO操作阻塞的時(shí)候,是不需要cpu參與的,這時(shí)候cpu就可以另開(kāi)一個(gè)線程去做別的事情,等待IO操作完成再回到之前的線程繼續(xù)執(zhí)行即可。

多線程帶來(lái)的問(wèn)題

其實(shí)多線程根本的問(wèn)題只有一個(gè):線程間變量的共享

java里的變量可以分3類(lèi):

  1. 類(lèi)變量(類(lèi)里面static修飾的變量)

  2. 實(shí)例變量(類(lèi)里面的普通變量)

  3. 局部變量(方法里聲明的變量)

下圖是jvm的內(nèi)存區(qū)域劃分圖:

seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營(yíng)銷(xiāo)培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營(yíng)銷(xiāo)培訓(xùn)

根據(jù)各個(gè)區(qū)域的定義,我們可以知道:

  1. 類(lèi)變量 保存在“方法區(qū)”

  2. 實(shí)例變量 保存在“堆”

  3. 局部變量 保存在 “虛擬機(jī)?!?/p>

“方法區(qū)”和“堆”都屬于線程共享數(shù)據(jù)區(qū),“虛擬機(jī)?!睂儆诰€程私有數(shù)據(jù)區(qū)。

因此,局部變量是不能多個(gè)線程共享的,而類(lèi)變量和實(shí)例變量是可以多個(gè)線程共享的。事實(shí)上,在java中,多線程間進(jìn)行通信的唯一途徑就是通過(guò)類(lèi)變量和實(shí)例變量。

也就是說(shuō),如果一段多線程程序中如果沒(méi)有類(lèi)變量和實(shí)例變量,那么這段多線程程序就一定是線程安全的。

以Web開(kāi)發(fā)的Servlet為例,一般我們開(kāi)發(fā)的時(shí)候,自己的類(lèi)繼承HttpServlet之后,重寫(xiě)doPost()、doGet()處理請(qǐng)求,不管我們?cè)谶@兩個(gè)方法里寫(xiě)什么代碼,只要沒(méi)有操作類(lèi)變量或?qū)嵗兞浚詈髮?xiě)出來(lái)的代碼就是線程安全的。如果在Servlet類(lèi)里面加了實(shí)例變量,就很可能出現(xiàn)線程安全性問(wèn)題,解決方法就是把實(shí)例變量改為T(mén)hreadLocal變量,而ThreadLocal實(shí)現(xiàn)的含義就是讓實(shí)例變量變成了“線程私有”的,即給每一個(gè)線程分配一個(gè)自己的值。

 

 現(xiàn)在我們知道:其實(shí)多線程根本的問(wèn)題只有一個(gè):線程間變量的共享,這里的變量,指的就是類(lèi)變量和實(shí)例變量,后續(xù)的一切,都是為了解決類(lèi)變量和實(shí)例變量共享的安全問(wèn)題。

如何安全的共享變量

現(xiàn)在唯一的問(wèn)題就是要讓多個(gè)線程安全的共享變量(下文中的變量一般特指類(lèi)變量和實(shí)例變量),上文提到了一種ThreadLocal的方式,其實(shí)這種方式并不是真正的共享,而是為每個(gè)線程分配一個(gè)自己的值。

網(wǎng)友評(píng)論