亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

Synchronized關鍵字同步類方法

系統 2038 0

轉載: http://java.chinaitlab.com/line/779782.html

要想解決“臟數據”的問題,最簡單的方法就是使用synchronized關鍵字來使run方法同步,代碼如下:

public ? synchronized ? void ?run()
{
???? ?
}

??? 從上面的代碼可以看出,只要在void和public之間加上synchronized關鍵字,就可以使run方法同步,也就是說,對于同一個 Java 類的對象實例,run方法同時只能被一個線程調用,并當前的run執行完后,才能被其他的線程調用。即使當前線程執行到了run方法中的yield方法,也只是暫停了一下。由于其他線程無法執行run方法,因此,最終還是會由當前的線程來繼續執行。先看看下面的代碼:

??? sychronized關鍵字只和一個對象實例綁定

?? class ?Test
??{
????????
public ? synchronized ? void ?method()
???????{
??????????? ?
???????}
??}
???
??
public ? class ?Sync? implements ?Runnable
??{
???????
private ?Test?test;
???????
public ? void ?run()
?????? {
????????? ? test.method();
?????? }
???? ?
public ?Sync(Test?test)
???? ? {
???????? ?
this .test? = ?test;
?????? }
?? ? ?
public ? static ? void ?main(String[]?args)? throws ?Exception
?? ? ? {
???????? ? Test?test1?
= ?? new ?Test();
??????? ?? Test?test2?
= ?? new ?Test();
?????????? Sync?sync1?
= ? new ?Sync(test1);
???????? ? Sync?sync2?
= ? new ?Sync(test2);
???????? ?
new ?Thread(sync1).start();
???????? ?
new ?Thread(sync2).start();?
?? ? ? }
?? }

??? 在Test類中的method方法是同步的。但上面的代碼建立了兩個Test類的實例,因此,test1和test2的method方法是分別執行的。要想讓method同步,必須在建立Sync類的實例時向它的構造方法中傳入同一個Test類的實例,如下面的代碼所示:

Sync?sync1? = ? new ?Sync(test1);

??? 不僅可以使用synchronized來同步非靜態方法,也可以使用synchronized來同步靜態方法。如可以按如下方式來定義method方法:

class ?Test?
{
??? public ? static ? synchronized ? void ?method()?{? ? ?}
}

??? 建立Test類的對象實例如下:

Test?test? = ? new ?Test();

??? 對于靜態方法來說,只要加上了synchronized關鍵字,這個方法就是同步的,無論是使用test.method(),還是使用Test.method()來調用method方法,method都是同步的,并不存在非靜態方法的多個實例的問題。

??? 在23種設計模式中的單件(Singleton)模式如果按傳統的方法設計,也是線程不 安全 的,下面的代碼是一個線程不 安全 的單件模式。

package ?test;

// ?線程安全的Singleton模式
class ?Singleton
{
????
private ? static ?Singleton?sample;

????
private ?Singleton()
????{
????}
????
public ? static ?Singleton?getInstance()
????{
????????
if ?(sample? == ? null )
????????{
????????????Thread.yield();?
// ?為了放大Singleton模式的線程不安全性
????????????sample? = ? new ?Singleton();
????????}
????????
return ?sample;
????}
}
public ? class ?MyThread? extends ?Thread
{
????
public ? void ?run()
????{
????????Singleton?singleton?
= ?Singleton.getInstance();
????????System.out.println(singleton.hashCode());
????}
????
public ? static ? void ?main(String[]?args)
????{
????????Thread?threads[]?
= ? new ?Thread[ 5 ];
????????
for ?( int ?i? = ? 0 ;?i? < ?threads.length;?i ++ )
????????????threads[i]?
= ? new ?MyThread();
????????
for ?( int ?i? = ? 0 ;?i? < ?threads.length;?i ++ )
????????????threads[i].start();
????}
}

??? 在上面的代碼調用yield方法是為了使單件模式的線程不安全性表現出來,如果將這行去掉,上面的實現仍然是線程不安全的,只是出現的可能性小得多。

??? 程序的運行結果如下:

25358555
26399554
7051261
29855319
5383406

??? 上面的運行結果可能在不同的運行環境上有所有同,但一般這五行輸出不會完全相同。從這個輸出結果可以看出,通過getInstance方法得到的對象實例是五個,而不是我們期望的一個。這是因為當一個線程執行了Thread.yield()后,就將CPU資源交給了另外一個線程。由于在線程之間切換時并未執行到創建Singleton對象實例的語句,因此,這幾個線程都通過了if判斷,所以,就會產生了建立五個對象實例的情況(可能創建的是四個或三個對象實例,這取決于有多少個線程在創建Singleton對象之前通過了if判斷,每次運行時可能結果會不一樣)。

??? 要想使上面的單件模式變成線程安全的,只要為getInstance加上synchronized關鍵字即可。代碼如下:

public ? static ? synchronized ?Singleton?getInstance()?{? ? ?}

??? 當然,還有更簡單的方法,就是在定義Singleton變量時就建立Singleton對象,代碼如下:

private ? static ? final ?Singleton?sample? = ? new ?Singleton();

??? 然后在getInstance方法中直接將sample返回即可。這種方式雖然簡單,但不知在getInstance方法中創建Singleton對象靈活。讀者可以根據具體的需求選擇使用不同的方法來實現單件模式。

?

在使用synchronized關鍵字時有以下四點需要注意:

??? 1.? synchronized關鍵字不能繼承。

??? 雖然可以使用synchronized來定義方法,但synchronized并不屬于方法定義的一部分,因此,synchronized關鍵字不能被繼承。如果在父類中的某個方法使用了synchronized關鍵字,而在子類中覆蓋了這個方法,在子類中的這個方法默認情況下并不是同步的,而必須顯式地在子類的這個方法中加上synchronized關鍵字才可以。當然,還可以在子類方法中調用父類中相應的方法,這樣雖然子類中的方法不是同步的,但子類調用了父類的同步方法,因此,子類的方法也就相當于同步了。這兩種方式的例子代碼如下:

??? 在子類方法中加上synchronized關鍵字

class ?Parent
{
???
public ? synchronized ? void ?method()?{? ? ?}
}
class ?Child? extends ?Parent
{
???
public ? synchronized ? void ?method()?{? ? ?}
}

??? 在子類方法中調用父類的同步方法

class ?Parent
{
??? public ? synchronized ? void ?method()?{? ? ?}
}
class ?Child? extends ?Parent
{
????
public ? void ?method()?{? super .method();? ? ?}
}

??? 2.? 在定義接口方法時不能使用synchronized關鍵字。

??? 3.? 構造方法不能使用synchronized關鍵字,但可以使用下節要討論的synchronized塊來進行同步。

??? 4.? synchronized可以自由放置。

??? 在前面的例子中使用都是將synchronized關鍵字放在方法的返回類型前面。但這并不是synchronized可放置唯一位置。在非靜態方法中,synchronized還可以放在方法定義的最前面,在靜態方法中,synchronized可以放在static的前面,代碼如下:

public ? synchronized ? void ?method();
synchronized ? public ? void ?method();
public ? static ? synchronized ? void ?method();
public ? synchronized ? static ? void ?method();
synchronized ? public ? static ? void ?method();

??? 但要注意,synchronized不能放在方法返回類型的后面,如下面的代碼是錯誤的:

public ? void ? synchronized ?method();
public ? static ? void ? synchronized ?method();

??? synchronized關鍵字只能用來同步方法,不能用來同步類變量,如下面的代碼也是錯誤的。

public ? synchronized ? int ?n? = ? 0 ;
public ? static ? synchronized ? int ?n? = ? 0 ;

??? 雖然使用synchronized關鍵字同步方法是最安全的同步方式,但大量使用synchronized關鍵字會造成不必要的資源消耗以及性能損失。雖然從表面上看synchronized鎖定的是一個方法,但實際上synchronized鎖定的是一個類。也就是說,如果在非靜態方法method1和method2定義時都使用了synchronized,在method1未執行完之前,method2是不能執行的。靜態方法和非靜態方法的情況類似。但靜態和非靜態方法不會互相影響。看看如下的代碼:

package ?test;

public ? class ?MyThread1? extends ?Thread
{
????
public ?String?methodName;

????
public ? static ? void ?method(String?s)
????{
????????System.out.println(s);
????????
while ?( true )
????????????;
????}
????
public ? synchronized ? void ?method1()
????{
????????method(
" 非靜態的method1方法 " );
????}
????
public ? synchronized ? void ?method2()
????{
????????method(
" 非靜態的method2方法 " );
????}
????
public ? static ? synchronized ? void ?method3()
????{
????????method(
" 靜態的method3方法 " );
????}
????
public ? static ? synchronized ? void ?method4()
????{
????????method(
" 靜態的method4方法 " );
????}
????
public ? void ?run()
????{
????????
try
????????{
????????????getClass().getMethod(methodName).invoke(
this );
????????}
????????
catch ?(Exception?e)
????????{
????????}
????}
????
public ? static ? void ?main(String[]?args)? throws ?Exception
????{
????????MyThread1?myThread1?
= ? new ?MyThread1();
????????
for ?( int ?i? = ? 1 ;?i? <= ? 4 ;?i ++ )
????????{
????????????myThread1.methodName?
= ? " method " ? + ?String.valueOf(i);
????????????
new ?Thread(myThread1).start();
????????????sleep(
100 );
????????}
????}
}

??? 運行結果如下:

非靜態的method1方法
靜態的method3方法

??? 從上面的運行結果可以看出,method2和method4在method1和method3未結束之前不能運行。因此,我們可以得出一個結論,如果在類中使用synchronized關鍵字來定義非靜態方法,那將影響這個中的所有使用synchronized關鍵字定義的非靜態方法。如果定義的是靜態方法,那么將影響類中所有使用synchronized關鍵字定義的靜態方法。這有點象數據表中的表鎖,當修改一條記錄時,系統就將整個表都鎖住了,因此,大量使用這種同步方式會使程序的性能大幅度下降。

?

?

Synchronized關鍵字同步類方法


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 亚洲精品美女国产一区 | 日韩欧美亚洲国产精品字幕久久久 | 色视频在线| sss欧美华人整片在线观看 | 亚洲精品国产第一区二区多人 | 国产91在线免费观看 | 日韩欧美高清视频 | 逼毛片| 久久综合九色综合精品 | 日韩一级片在线观看 | 日本特黄a级高清免费大片18 | 亚洲国产精品综合久久2007 | 日日操天天操夜夜操 | 国产精品福利在线观看免费不卡 | 激情五月综合综合久久69 | 青青青爽线在线视频观看 | 国产精品亚洲精品日韩已满 | 天天操天天摸天天干 | 久久天天丁香婷婷中文字幕 | 国产精品夜色视频一区二区 | 欧美成人另类 | 国产国拍亚洲精品午夜不卡17 | 999热精品这里在线观看 | 青娱乐国产在线视频 | 久久亚洲不卡一区二区 | 久久精品精品 | 亚洲欧美日韩在线不卡中文 | 国产一区二区三区免费观看 | 在线观看深夜观看网站免费 | 国内精品久久久久激情影院 | 久久免费在线视频 | 国内精品久久久久激情影院 | 成年人黄色在线观看 | 国产精品久久久久无码av | 日韩第3页 | 97视频免费公开成人福利 | 亚洲欧美日韩国产vr在线观 | 国产精品美女一区二区 | 欧美日韩一级大片 | 26uuu色噜噜欧美在线播放 | 伊人干综合网 |