薛 嵐(江西信息應(yīng)用職業(yè)技術(shù)學(xué)院 計(jì)算機(jī)技術(shù)系,南昌 330043)
同步機(jī)制實(shí)現(xiàn)多線程有序訪問(wèn)資源
薛嵐
(江西信息應(yīng)用職業(yè)技術(shù)學(xué)院計(jì)算機(jī)技術(shù)系,南昌330043)
摘要:當(dāng)多個(gè)線程競(jìng)爭(zhēng)訪問(wèn)同一個(gè)資源時(shí),Java提供了線程同步這種機(jī)制來(lái)協(xié)調(diào)各個(gè)線程的訪問(wèn)。由于線程同步的復(fù)雜性,很多時(shí)候開(kāi)發(fā)人員弄不清楚資源是什么、線程何時(shí)處于競(jìng)爭(zhēng)狀態(tài),線程同步如何使用等問(wèn)題,本文將對(duì)線程同步問(wèn)題做深入探討。
關(guān)鍵詞:線程;同步;資源;鎖
多線程是指在同一個(gè)程序中同時(shí)存在幾個(gè)執(zhí)行體,按幾條不同的執(zhí)行路徑共同工作的情況。Java允許多線程并發(fā)控制,當(dāng)多個(gè)線程訪問(wèn)同一資源時(shí),也就是多個(gè)線程同時(shí)競(jìng)爭(zhēng)一個(gè)資源同時(shí)操作一個(gè)可共享的資源變量時(shí)(如數(shù)據(jù)的增刪改查),將會(huì)導(dǎo)致數(shù)據(jù)不準(zhǔn)確,相互之間產(chǎn)生沖突,如果協(xié)調(diào)不好就會(huì)出現(xiàn)數(shù)據(jù)不一致的問(wèn)題。因此當(dāng)多個(gè)線程訪問(wèn)同一資源時(shí),因此加入同步鎖讓某一個(gè)線程獨(dú)占此資源,也就是鎖定該資源,其它線程在此時(shí)此刻不能訪問(wèn)該資源,以避免在該線程沒(méi)有完成操作之前,被其他線程的調(diào)用,稱(chēng)為線程同步。從而保證了該變量的唯一性和準(zhǔn)確性。
在Java代碼中運(yùn)用線程同步機(jī)制,有兩個(gè)關(guān)鍵處的代碼需要完成:1、當(dāng)多個(gè)線程競(jìng)爭(zhēng)訪問(wèn)同一個(gè)對(duì)象或同一變量時(shí),該對(duì)象或變量為競(jìng)爭(zhēng)資源標(biāo)識(shí)為private;2、當(dāng)某一個(gè)方法或某一段代碼在某一個(gè)時(shí)刻只能被一個(gè)線程獨(dú)自訪問(wèn),用synchronized關(guān)鍵字標(biāo)識(shí)方法或代碼為同步。synchronized只能標(biāo)記非抽象的方法,不能標(biāo)識(shí)成員變量。
(1)synchronized方法。用synchronized關(guān)鍵字修飾一個(gè)方法,該方法為同步方法。Java中的每個(gè)對(duì)象資源都有一個(gè)鎖,或者叫做監(jiān)視器,當(dāng)一個(gè)線程訪問(wèn)某個(gè)對(duì)象的同步方法時(shí),該對(duì)象被鎖住,其他任何線程無(wú)法去訪問(wèn)該對(duì)象的同步方法了,相當(dāng)于對(duì)象被一個(gè)線程獨(dú)占。直到該線程線程執(zhí)行方法完畢后(或者是拋出了異常),才將該對(duì)象解鎖,釋放對(duì)象資源,其他線程才有可能再去訪問(wèn)該對(duì)象的同步方法。
用同步方法實(shí)現(xiàn)類(lèi)成員變量的訪問(wèn):Java系統(tǒng)為每個(gè)類(lèi)實(shí)例都配了一把鎖,當(dāng)要用類(lèi)實(shí)例來(lái)調(diào)用同步方法時(shí)需要獲得這個(gè)類(lèi)實(shí)例的鎖才能執(zhí)行,此時(shí)進(jìn)入線程運(yùn)行狀態(tài),否則就為線程阻塞。
同步方法一旦被執(zhí)行執(zhí)行,其它類(lèi)實(shí)例將無(wú)法訪問(wèn),直到同步方法返回釋放鎖,其它類(lèi)實(shí)例才有可能訪問(wèn)此方法。被阻塞的其它線程才能獲得該鎖,重新進(jìn)入可執(zhí)行狀態(tài)。這種機(jī)制保證了類(lèi)中所有同步成員方法在同一時(shí)刻只有一個(gè)可被類(lèi)實(shí)例訪問(wèn),因?yàn)橹挥蝎@得了類(lèi)實(shí)例對(duì)應(yīng)的鎖的同步成員方法才能被訪問(wèn),從而有效避免了類(lèi)成員方法的訪問(wèn)矛盾。在Java中,除了類(lèi)實(shí)例以外,每一個(gè)類(lèi)也對(duì)應(yīng)一把鎖,因此也可將類(lèi)的靜態(tài)成員方法聲明為同步,以避免對(duì)類(lèi)的靜態(tài)成員的訪問(wèn)沖突。
同步方法的缺點(diǎn):有些方法若聲明為同步將會(huì)很大程度地降低執(zhí)行效率,線程類(lèi)的run()方法不能聲明為同步,否則它對(duì)本類(lèi)中的任何同步方法的調(diào)用都不會(huì)成功。同步機(jī)制需要占用大量?jī)?nèi)存,而且如果使用不當(dāng)易造成死鎖。
(2)synchronized塊。將需要被線程獨(dú)占訪問(wèn)的代碼用大括號(hào)括起來(lái)前面標(biāo)識(shí)為synchronized,則系統(tǒng)自動(dòng)為該段語(yǔ)句塊加上內(nèi)置鎖,從而構(gòu)成同步代碼塊。
同步代碼塊中的代碼必須獲得類(lèi)對(duì)象或類(lèi)的鎖才能被線程訪問(wèn)執(zhí)行。由于任何代碼塊都可以標(biāo)識(shí)為同步,并且可獲得任意對(duì)象上的鎖,所以同步代碼塊運(yùn)用方便靈活。
(3)使用特殊域變量實(shí)現(xiàn)線程同步。1).volatile關(guān)鍵字為域變量的訪問(wèn)提供了一種免鎖機(jī)制;2).使用volatile修飾域相當(dāng)于告訴虛擬機(jī)該域可能會(huì)被其他線程更新;3).因此每次使用該域就要重新計(jì)算,而不是使用寄存器中的值;4).volatile不會(huì)提供任何原子操作,它也不能用來(lái)修飾final類(lèi)型的變量
(4)使用重入鎖實(shí)現(xiàn)線程同步??芍厝氲幕コ怄i具有與使用同步方法和語(yǔ)句所訪問(wèn)的隱式監(jiān)視器鎖相同的一些基本行為和語(yǔ)義,但功能更強(qiáng)大。它由最近成功獲得鎖,并且還沒(méi)有釋放該鎖的線程擁有。
(5)使用局部變量實(shí)現(xiàn)線程同步
(1)無(wú)論方法還是代碼標(biāo)識(shí)為同步,鎖住的資源是指對(duì)象,而且只要不是多個(gè)線程同時(shí)訪問(wèn)同步方法和代碼塊,其還可以被其他線程的對(duì)象訪問(wèn),。
(2)每個(gè)對(duì)象只對(duì)應(yīng)一個(gè)鎖,即一個(gè)對(duì)象只與一個(gè)鎖相關(guān)聯(lián)。
(3)使用同步機(jī)制時(shí)需要謹(jǐn)慎,能不用同步實(shí)現(xiàn)的操作就不用同步實(shí)現(xiàn)。因?yàn)槭褂猛叫枰加煤艽蟮南到y(tǒng)內(nèi)存,開(kāi)銷(xiāo)很大就有可能造成死鎖。
(4)當(dāng)兩個(gè)線程同時(shí)搶占同一個(gè)對(duì)象中的同步方法或變量時(shí),只能有一個(gè)線程可以執(zhí)行訪問(wèn)同步方法或變量。另一個(gè)線程進(jìn)入暫時(shí)等待狀態(tài)必須等待當(dāng)前線程執(zhí)行完才能訪問(wèn)。
(5)當(dāng)一個(gè)線程訪問(wèn)對(duì)象中的一個(gè)同步代碼塊時(shí),這個(gè)對(duì)象中的其它同步代碼塊也會(huì)被鎖住,也就是對(duì)其它線程關(guān)閉。
(6)當(dāng)一個(gè)線程訪問(wèn)對(duì)象的一個(gè)同步代碼塊時(shí),該對(duì)象中的非同步方法或變量不受影響,可以被其它線程訪問(wèn)。
(7)當(dāng)一個(gè)線程訪問(wèn)一個(gè)對(duì)象的某個(gè)同步代碼塊時(shí),該對(duì)象的對(duì)象鎖就自動(dòng)賦給了此線程。即此線程獨(dú)占該對(duì)象的所有同步方法和變量,禁止同一時(shí)刻其它線程對(duì)該對(duì)象上任何同步方法和變量的訪問(wèn)。
(1)線程同步機(jī)制是為了防止多個(gè)線程競(jìng)爭(zhēng)同一資源時(shí)由于沒(méi)協(xié)調(diào)好而出現(xiàn)線程對(duì)資源數(shù)據(jù)修改的不一致。
(2)線程同步機(jī)制需要通過(guò)鎖來(lái)實(shí)現(xiàn),每個(gè)對(duì)象都有一把鎖。當(dāng)一個(gè)線程獲得了一個(gè)對(duì)象上的鎖,其它線程在同一時(shí)刻就不能訪問(wèn)該對(duì)象上的所有同步方法和同步變量
(3)對(duì)于靜態(tài)同步方法,鎖是針對(duì)這個(gè)類(lèi)的,鎖對(duì)象是該類(lèi)的Class對(duì)象。靜態(tài)和非靜態(tài)方法的鎖互不干預(yù)。一個(gè)線程獲得鎖,在一個(gè)同步方法中訪問(wèn)另一個(gè)對(duì)象上的同步方法時(shí),會(huì)獲取這兩個(gè)對(duì)象鎖。
(4)使用同步時(shí),要注意在是哪個(gè)對(duì)象上同步,否則會(huì)出現(xiàn)對(duì)象不一致。
(5)當(dāng)多個(gè)線程競(jìng)爭(zhēng)一個(gè)資源時(shí),只有獲得對(duì)象鎖的線程才能訪問(wèn)資源,沒(méi)有獲取對(duì)象鎖的線程將處于暫時(shí)阻塞狀態(tài)。
(6)死鎖是多個(gè)線程需要獲得其它線程占有的資源后才能完成操作,而每個(gè)線程又都不肯釋放自己占有的資源,造成永遠(yuǎn)相互等待。
參考文獻(xiàn):
[1]張榮海.Java多線程同步方法的研究[J].黑龍江科技信息,2003 (05).
作者簡(jiǎn)介:薛嵐(1980-),女,江西南昌人,碩士,講師,研究方向:軟件技術(shù)專(zhuān)業(yè)Java方向。