97干视频,99国产精品懂色,亚洲精品99久久久久中文字幕,伊人五月丁香综合AⅤ,国产精品成人免费999

  您的位置:華清遠(yuǎn)見教育科技集團(tuán) >> 新聞動(dòng)態(tài) >> Android資料 >> Java Synchronized同步關(guān)鍵字的用法  
 
Java Synchronized同步關(guān)鍵字的用法
分享到:

synchronized關(guān)鍵字屬于操作系統(tǒng)的范疇,與同步對(duì)應(yīng)的是異步。在程序設(shè)計(jì)的概念中,有同步調(diào)用或者異步調(diào)用,同步是指該段代碼(方法)從調(diào)用開始,直到內(nèi)部執(zhí)行完畢后才能返回;異步調(diào)用是指調(diào)用該段代碼(方法)后立即返回,無論該段代碼內(nèi)部所執(zhí)行的物理操作是否執(zhí)行完畢,異步代碼一般存在于多線程程序設(shè)計(jì)中,單線程程序內(nèi)部不存在異步調(diào)用。

synchronized關(guān)鍵字的作用就是告訴操作系統(tǒng),在執(zhí)行該關(guān)鍵字所限定的代碼片段內(nèi),不允許被其他線程打斷。在一般的操作系統(tǒng)設(shè)計(jì)中,會(huì)提供一個(gè)類似于synchronized的API方法,而Java則是給了這樣一個(gè)關(guān)鍵字,相當(dāng)于說,Java編譯器為操作系統(tǒng)分擔(dān)了一部分工作。

那么,什么情況下需要使用synchronized關(guān)鍵字呢?凡是需要某段代碼在執(zhí)行時(shí)不被其他線程打斷時(shí),都可以加上synchronized關(guān)鍵字,舉例如代碼清單1-1所示。

代碼清單1-1 synchronized關(guān)鍵字

public class MyMusicWidgetProvider{
        private static MyMusicWidgetProvider sInstance;
        static synchronized MyMusicWidgetProvider getInstance(){
            if(sInstance==null)
                sInstance=new MyMusicWidgetProvider();
            returnsInstance;
        }
    }

以上代碼定義了一個(gè)類,并希望該類在運(yùn)行時(shí)僅有一個(gè)實(shí)例,每次調(diào)用該類所包含的方法時(shí),先得到該類的實(shí)例,然后再通過實(shí)例調(diào)用其他方法。該類有一個(gè)static的getInstance()方法,該方法的作用就是檢查是否存在一個(gè)實(shí)例,如果沒有就創(chuàng)建一個(gè),否則返回存在的實(shí)例。

getInstance()方法前面加了synchronized關(guān)鍵字,為的是該方法在執(zhí)行時(shí)不能被其他線程打斷,那么,為什么有這樣的要求呢?試想一下,假設(shè)沒有使用該關(guān)鍵字,第1個(gè)線程A 在執(zhí)行g(shù)etInstance()方法時(shí),方法體中的new 運(yùn)算符剛剛創(chuàng)建了一個(gè)MyMusicWidgetProvider實(shí)例,但還沒來得及把實(shí)例賦值給sInstance,而此時(shí)B線程又來調(diào)用getInstance()方法,出現(xiàn)這種情況的原因是:sInstance= new MyMusicWidgetProvider()這句代碼會(huì)被Java編譯器編譯成多條機(jī)器指令,其中給sInstance賦值的機(jī)器指令和創(chuàng)建一個(gè)MyMusicWidgetProvider對(duì)象的機(jī)器指令是分開的。此時(shí)對(duì)于B線程來講,它會(huì)重新檢查sInstance是否為空,由于A線程還沒有來得及給sIntance賦值,因此,B線程就會(huì)再次創(chuàng)建一個(gè)新的MyMusicWidgetProvider實(shí)例,當(dāng)B線程暫停并返回A 線程時(shí),A 線程會(huì)把第1次創(chuàng)建的實(shí)例重新賦值給sInstance,這就會(huì)導(dǎo)致B線程將來對(duì)MyMusicWidgetProvider實(shí)例的錯(cuò)誤引用,因?yàn)锽線程所創(chuàng)建實(shí)例的地址被A線程修改了。

因此,這就要求getInstance()一旦開始執(zhí)行,必須執(zhí)行完畢后才能返回,中間不能被其他線程打斷。

sychronized除了約束整個(gè)方法外,也可以約束一小段代碼,這樣做的好處有兩個(gè):一個(gè)是可以避免定義新方法;另一個(gè)是能夠避免一些線程同步問題,如代碼清單1-2所示。

代碼清單1-2 synchronized約束小段代碼

Object obj;
    int c;
    void addMethod(){
        synchronized(obj){
            c++;
            //其他代碼
        }
    }

obj可以是任意類型的一個(gè)對(duì)象,該對(duì)象的唯一作用就是給synchronized提供一個(gè)“鎖”。同步設(shè)計(jì)的原則之一是盡量減少同步中包含的代碼大小,從而在線程間能夠更平衡地運(yùn)行。因此,同步一小段代碼是一個(gè)不錯(cuò)的做法。同時(shí),假設(shè)addMethod()內(nèi)部還調(diào)用了其他同步方法,那么,從這個(gè)同步跳到另外的同步會(huì)增加線程間死鎖的風(fēng)險(xiǎn),因此不同步整個(gè)addMethod()而僅同步局部代碼,這就是第2個(gè)好處。

擴(kuò)展閱讀:關(guān)于共享資源的同步訪問安全問題

1. 定義private 的instance變量+它的 get方法,而不要定義public/protected的instance變量。如果將變量定義為public,對(duì)象在外界可以繞過同步方法的控制而直接取得它,并改動(dòng)它。這也是JavaBean的標(biāo)準(zhǔn)實(shí)現(xiàn)方式之一。

2. 如果instance變量是一個(gè)對(duì)象,如數(shù)組或ArrayList什么的,那上述方法仍然不安全,因?yàn)楫?dāng)外界對(duì)象通過get方法拿到這個(gè)instance對(duì)象的引用后,又將其指向另一個(gè)對(duì)象,那么這個(gè)private變量也就變了,豈不是很危險(xiǎn)。 這個(gè)時(shí)候就需要將get方法也加上synchronized同步,并且,只返回這個(gè)private對(duì)象的clone()――這樣,調(diào)用端得到的就是對(duì)象副本的引用了。

 更多相關(guān)文章

·Android Map類的使用方法
·Abstract class和Interface的使用
·Android Interface的使用
·Android程序UI設(shè)計(jì)
·AndroidManifest.xml文件詳解