Java線程同步問題在實(shí)踐中尋找答案
Java線程同步需要我們不斷的學(xué)習(xí),在學(xué)習(xí)的時(shí)候我們會遇到不少的問題,其實(shí)我們在前面講了為什么要Java線程同步,下面我們就來看如何才能線程同步。希望我們大家有所收獲。
Java線程同步的基本實(shí)現(xiàn)思路還是比較容易理解的。我們可以給共享資源加一把鎖,這把鎖只有一把鑰匙。哪個(gè)線程獲取了這把鑰匙,才有權(quán)利訪問該共享資源。生活中,我們也可能會遇到這樣的例子。一些超市的外面提供了一些自動儲物箱。每個(gè)儲物箱都有一把鎖,一把鑰匙。人們可以使用那些帶有鑰匙的儲物箱,把東西放到儲物箱里面,把儲物箱鎖上,然后把鑰匙拿走。這樣,該儲物箱就被鎖住了,其他人不能再訪問這個(gè)儲物箱。(當(dāng)然,真實(shí)的儲物箱鑰匙是可以被人拿走復(fù)制的,所以不要把貴重物品放在超市的儲物箱里面。于是很多超市都采用了電子密碼鎖。)
Java線程同步鎖這個(gè)模型看起來很直觀。但是,還有一個(gè)嚴(yán)峻的問題沒有解決,這個(gè)同步鎖應(yīng)該加在哪里? 當(dāng)然是加在共享資源上了。反應(yīng)快的讀者一定會搶先回答。#t#
沒錯(cuò),如果可能,我們當(dāng)然盡量把同步鎖加在共享資源上。一些比較完善的共享資源,比如,文件系統(tǒng),數(shù)據(jù)庫系統(tǒng)等,自身都提供了比較完善的同步鎖機(jī)制。我們不用另外給這些資源加鎖,這些資源自己就有鎖。
但是,大部分情況下,我們在代碼中訪問的共享資源都是比較簡單的共享對象。這些對象里面沒有地方讓我們加鎖。讀者可能會提出建議:為什么不在每一個(gè)對象內(nèi)部都增加一個(gè)新的區(qū)域,專門用來加鎖呢?這種設(shè)計(jì)理論上當(dāng)然也是可行的。問題在于,Java線程同步的情況并不是很普遍。如果因?yàn)檫@小概率事件,在所有對象內(nèi)部都開辟一塊鎖空間,將會帶來極大的空間浪費(fèi)。得不償失。
于是,現(xiàn)代的編程語言的設(shè)計(jì)思路都是把同步鎖加在代碼段上。確切的說,是把同步鎖加在“訪問共享資源的代碼段”上。這一點(diǎn)一定要記住,同步鎖是加在代碼段上的。
同步鎖加在代碼段上,就很好地解決了上述的空間浪費(fèi)問題。但是卻增加了模型的復(fù)雜度,也增加了我們的理解難度。現(xiàn)在我們就來仔細(xì)分析“同步鎖加在代碼段上”的Java線程同步模型。
首先,我們已經(jīng)解決了同步鎖加在哪里的問題。我們已經(jīng)確定,同步鎖不是加在共享資源上,而是加在訪問共享資源的代碼段上。
其次,我們要解決的問題是,我們應(yīng)該在代碼段上加什么樣的鎖。這個(gè)問題是重點(diǎn)中的重點(diǎn)。這是我們尤其要注意的問題:訪問同一份共享資源的不同代碼段,應(yīng)該加上同一個(gè)同步鎖;如果加的是不同的同步鎖,那么根本就起不到同步的作用,沒有任何意義。
這就是說,同步鎖本身也一定是多個(gè)線程之間的共享對象。