轉(zhuǎn):Java同步技術(shù)(一)

本文版權(quán)歸作者Ian Gao所有,如有轉(zhuǎn)載請(qǐng)與作者聯(lián)系并注明出處http://blog.csdn.net/Iangao/archive/2008/10/09/3041265.aspx。

成都創(chuàng)新互聯(lián)公司專(zhuān)業(yè)IDC數(shù)據(jù)服務(wù)器托管提供商,專(zhuān)業(yè)提供成都服務(wù)器托管,服務(wù)器租用,服務(wù)器托管,服務(wù)器托管,成都多線(xiàn)服務(wù)器托管等服務(wù)器托管服務(wù)。

一、基本同步原理

1.1 同步機(jī)制(synchronize mechanism)

1.1.1 同步

多線(xiàn)程開(kāi)發(fā)過(guò)程中,我們經(jīng)常會(huì)提到同步這個(gè)詞,那么什么是同步呢?為什么會(huì)存在同步問(wèn)題呢?我們知道一個(gè)多線(xiàn)程應(yīng)用系統(tǒng)在操作系統(tǒng)的進(jìn)程(線(xiàn)程)機(jī)制下可以同時(shí)有多個(gè)進(jìn)程(線(xiàn)程)并發(fā)運(yùn)行,這此進(jìn)程(線(xiàn)程)要完成的任務(wù)可能是互不相關(guān)的,但也可能是有聯(lián)系的。那么當(dāng)一個(gè)進(jìn)程(線(xiàn)程)要和另一個(gè)進(jìn)程(線(xiàn)程)交流信息時(shí)同步就有可能發(fā)生了。為什么呢?如果您不清,看了下面這個(gè)例子也許就會(huì)明白了。

[@more@]

同步示例: 進(jìn)程同步:// http://www.csdn.net/blog/Iangao
在日常生活中我們經(jīng)常會(huì)遇到定蛋糕的事,過(guò)程是什么樣的呢?讓我們一起來(lái)回顧一下。
首先是我們做我們的事,蛋糕師傅也做道自已的事,當(dāng)我們想要買(mǎi)蛋糕時(shí),我們就要和蛋糕師打交道了。
我們選好蛋糕樣式,交款完款,把定單交給蛋糕師后由于時(shí)間制作時(shí)間很長(zhǎng),所以出去逛20分鐘的街,然后回來(lái)拿著小票等待蛋糕被做好了。
蛋糕師則是一上班就在等待定單,當(dāng)他拿到定單后,開(kāi)始按照要求進(jìn)行制作,做好后把這蛋糕放到貨架上,然后根據(jù)定單上的連系方式通知我們來(lái)取貨。
接到通知單后,我們便可以拿著蛋糕回家了。而蛋糕師還將繼續(xù)做著他自已的事情。 貨架,定單,取貨通知單
顧客進(jìn)程 師傅進(jìn)程
顧客(){
選擇蛋糕() // 1.(并行)

交款() // 2.(并行)
出示(定單) // 3. (同步1)
逛街(20分鐘) // 4. (并行)
等待(取貨) // 5. (同步2)
// http://www.csdn.net/blog/Iangao

取蛋糕(貨架) // 7. (并行)
回家() // 8. (并行)

}// http://www.csdn.net/blog/Iangao 制作(){
準(zhǔn)備制作() // 1(并行)
while(true){
等待(定單) // 2.(同步1)

制作(30分鐘) // 4.(并行)
放入蛋糕(貨架) // 5.
通知(取貨) // 6. (同步2)
... // 7. (并行)
}
}

我們分析一下上面的例子,在例子中,我們可以看出由于沒(méi)有定單,師傅進(jìn)程在“同步1”處不得不停下來(lái)等待一個(gè)定單,直到有定單時(shí)它才可以制作蛋糕。同樣的,由于蛋糕尚未做好,因此顧客線(xiàn)程也在“同步2”處停下來(lái)等待,直到接到取貨通知單后才取蛋糕回家?,F(xiàn)在我們可以總結(jié)一下:同步(synchronize)實(shí)際上就是讓一個(gè)線(xiàn)程停下腳步處于等待狀態(tài)直到另一個(gè)線(xiàn)程向它發(fā)出繼續(xù)執(zhí)行的信號(hào)后,兩個(gè)線(xiàn)程再繼續(xù)并發(fā)執(zhí)行的一種線(xiàn)程間的通信機(jī)制。而通過(guò)上面的例子我們可以總結(jié)出“要想實(shí)現(xiàn)這種機(jī)制起碼應(yīng)該具備如下三個(gè)基本要素”:

一個(gè)用于通信的信號(hào)(signal)
一個(gè)用于等待信號(hào)的操作(wait)
一個(gè)用于發(fā)送信號(hào)的操作(notify)
這種機(jī)制在Solaris或POSIX線(xiàn)程中,它們通常被看做是條件變量(condition variable), 而在Windows系統(tǒng)中它們往往被看成是事件變量(event variable),不過(guò)兩者還是有一些區(qū)別的,我們將在后面的章節(jié)中繼續(xù)深入討論。

1.1.2 臨界區(qū)、鎖

在同步問(wèn)題中,有一類(lèi)是由于對(duì)共享資源并發(fā)使用而引起的。眾所周知一組資源(數(shù)據(jù))被多個(gè)進(jìn)程(線(xiàn)程)同時(shí)使用,往往會(huì)造成邏輯紊亂(有的在讀,有的在改),為了避免這一情況,就要求對(duì)資源的使用加以控制,使得進(jìn)程(線(xiàn)程)在訪問(wèn)資源期間,不允許被其他進(jìn)程(線(xiàn)程)干擾。有干擾的線(xiàn)程必須處于等待狀態(tài)中。通常我們把這段不受干擾的使用某一特定資源的段碼段稱(chēng)為該資源的臨界區(qū)(critical section)。而臨界區(qū)就象對(duì)資源加了一把鎖(Lock),進(jìn)的時(shí)候加鎖(lock),出的時(shí)解鎖(unlock),這就可以把所有有干擾的進(jìn)程(線(xiàn)程)鎖都到臨界區(qū)之外。下面我們分析一下用于定義臨界區(qū)的鎖操作都完成了什么功能,請(qǐng)看下面的一個(gè)最簡(jiǎn)單的功能性說(shuō)明代碼清單(下圖參考自《操作系統(tǒng)》一書(shū)):

shared double balance, account; //共享變量
shared int lock=FALSE; //同步變量(Mutex): 用于實(shí)現(xiàn)控制對(duì)balance和account資源訪問(wèn)的鎖
Program for P1 [ Credit(貸) ]
// http://www.csdn.net/blog/Iangao
...
enter(lock); // 1. 進(jìn)入臨界區(qū)(加鎖)
balance=balance+account; // 2. <臨界區(qū)A>
leave(lock); // 3. 離開(kāi)臨界區(qū)(解鎖)
---------------------------------------------------------->
... // 4. 繼續(xù)P1任務(wù) Program for P1 [ Debit(借) ]
// http://www.csdn.net/blog/Iangao
...
enter(lock); // 2. 等待P1解鎖
// http://www.csdn.net/blog/Iangao


balance=balance-account; // 4. <臨界區(qū)B> (獲取了P1釋放的鎖)
leave(lock); // 5. 解鎖
...

1.1.3 互斥鎖

隨著后面不斷深入的討論,我們會(huì)發(fā)現(xiàn)有些臨界區(qū)的鎖是可以有限度的,它只阻止一部分可以引起相互干擾的進(jìn)程(線(xiàn)程)進(jìn)入臨界區(qū),而不會(huì)阻止互不干擾的進(jìn)程(線(xiàn)程)進(jìn)入,這時(shí)可能會(huì)有幾個(gè)進(jìn)程(線(xiàn)程)并發(fā)的使用。不過(guò)本節(jié)我們只討論其中一種最簡(jiǎn)單的鎖,一種會(huì)阻隔一切想要進(jìn)入臨界區(qū)內(nèi)線(xiàn)程的鎖,由于它具有極強(qiáng)的排它性,因此我們稱(chēng)它為互斥量(Mutex lock)。同樣由于它具有排它性,我們一般會(huì)用它來(lái)定義一個(gè)原子(atomic)操作,因?yàn)樗梢院芎玫谋WC對(duì)某一資源操作的不可分割性(individed)。下面我們簡(jiǎn)單定義了一個(gè)mutex的基本語(yǔ)義:

// 加鎖:原子操作
enter(mutex){
while(mutex) wait(); // 等待
mutex=TRUE; // 標(biāo)識(shí)資源忙
} // 解鎖:原子操作
leave(mutex){
mutex=FALSE; // 標(biāo)識(shí)資源可用
notify();
}

考虎到mutex是用于定義原子操作的,因此我們?cè)趯?shí)現(xiàn)時(shí)會(huì)對(duì)加鎖和解鎖操作進(jìn)行一定的約束,約束如下:

最后,為了保證臨界的原子性(atomic),通常對(duì)一個(gè)互斥量Mutex做解鎖操作的進(jìn)程(線(xiàn)程)一定是前面對(duì)其進(jìn)行加鎖操作的進(jìn)程。 而不允許被其他進(jìn)程(線(xiàn)程)解鎖。下面的代碼清單演示了臨界區(qū)與鎖的工作原理:如果P1運(yùn)行到balance=balance+account時(shí)P2運(yùn)行到了enter(lock),那么由于P1對(duì)"lock資源"已經(jīng)加鎖了,此時(shí)P2只處于等待狀態(tài)。直到P1執(zhí)行完exit(lock)后才釋放了對(duì)"lock資源"的控制權(quán),這時(shí)P2使可以執(zhí)行enter(lock)操作,繼而在獨(dú)占lock資源的情況下完成臨界區(qū)中的代碼示意圖。

1.2 Java中的同步機(jī)制

1.2.1 synchronized關(guān)鍵字

1 定義臨界區(qū):

Java為了實(shí)現(xiàn)同步機(jī)制提供了synchronized關(guān)鍵字,我們可以使用它來(lái)定義被同步的對(duì)象以及臨界區(qū),臨界區(qū)的范圍是由一組大括號(hào)來(lái)標(biāo)識(shí)的。而進(jìn)出臨界區(qū)時(shí)必要的加鎖和解鎖操作則是由Java內(nèi)置支持的。從功能上來(lái)說(shuō),我們可以認(rèn)為左大括號(hào)起到enter(lock)的作用,而右大括號(hào)起到了exit(lock)的作用。下面清單中演示了synchronized與互斥鎖理論功能上的的對(duì)應(yīng)關(guān)系。

private double balance, account; //共享變量
private Object lock=new Object(); //同步對(duì)象

Program for P1
...
synchronized(lock){ // 獲取資源并加鎖
balance=balance+account; // <臨界區(qū)>
} // 釋放資源并解鎖
... shared double balance, account; //共享變量
shared int lock=FALSE; //同步變量

Program for P1
...
enter(lock); // 獲取資源并加鎖
balance=balance+account; // <臨界區(qū)>
exit(lock); // 釋放資源并解鎖
...

2 定義同步對(duì)象:

我們知道了如何定義臨界區(qū),但這還不夠,我們還需要知道如何定義這段臨界區(qū)要同步的對(duì)象(數(shù)據(jù)).在Java中有下面的兩種使用synchronized的方式,我們分別看一下它們是如何定義被同步的對(duì)象的:

一種是直接“聲明同步(synchronized)對(duì)象”: 這種方式的同步對(duì)象被明確的指定在了sychronized后的小括號(hào),而其后的一組大括號(hào)內(nèi)定義的正是臨界區(qū)。這種方式使用起來(lái)很靈活,可以只對(duì)方法中的一段不可分割的代碼做同步,因此臨界區(qū)比較小,所以效率也就可以比較高了。下面清單中演示了這一用法的使用。
/**
* 聲明同步對(duì)象示例,參看上節(jié)示例
* @author iangao
*/// http://www.csdn.net/blog/Iangao
public class Foo {
private double balance, amount; //共享資源
private Object synObject=new Object(); //同步對(duì)象
/**
* 參看上節(jié): [Program for P1]
*/
public void f(){
...
// 進(jìn)入 臨界區(qū),鎖定對(duì)synObj的訪問(wèn)
synchronized(synObject){ // 臨界區(qū)A
balance=balance+amount;
...// http://www.csdn.net/blog/Iangao
doSomethingInCriticalSectionA();
}
// 退出 臨界區(qū),釋放對(duì)synObj的鎖定// http://www.csdn.net/blog/Iangao
...
}// http://www.csdn.net/blog/Iangao
/**
* 參看上節(jié): [Program for P2]
*/
public void g(){// http://www.csdn.net/blog/Iangao
...
synchronized(synObject){ // 臨界區(qū)B
balance=balance-amount;
...
doSomethingInCriticalSectionB();
}
....// http://www.csdn.net/blog/Iangao
}
}

另一種是“聲明同步(synchronized)方法”:這種方式是把整個(gè)方法的實(shí)現(xiàn)都劃入了臨界區(qū).但它同步的是哪個(gè)對(duì)象呢?實(shí)際上這種方式是隱式的對(duì)this對(duì)象做同步的,相當(dāng)于一進(jìn)入方法就對(duì)this對(duì)象做同步操作[即synchronized(this){}],直到方法結(jié)束 再解除同步。不過(guò)因?yàn)槭菍?duì)整個(gè)方法 做同步,所以有時(shí)會(huì)顯得效率不高,只是它用起來(lái)很方便。以下清單中描述了synchronized的這種用法,右邊演示了重構(gòu)成第一種使用方式時(shí)的樣子。
/**
* 聲明同步方法示例 (管程的Java實(shí)現(xiàn))
* @author iangao
*/
public class Foo2 {// http://www.csdn.net/blog/Iangao
private double balance, amount; //共享資源
public synchronized void f(){ // 監(jiān)界區(qū)C
balance=balance+amount;
}// http://www.csdn.net/blog/Iangao
public synchronized void g(){ // 監(jiān)界區(qū)D
balance=balance-amount;
}
}// http://www.csdn.net/blog/Iangao /**
* 按照同步對(duì)象的方法重構(gòu)Foo2后
* @author iangao
*/
public class Foo2 {
private double balance, amount; //共享資源
public void f(){
synchronized(this){ // 監(jiān)界區(qū)C
balance=balance+amount;
}
}
public void g(){
synchronized(this){ // 監(jiān)界區(qū)D
balance=balance-amount;
}
}
}

其實(shí),通過(guò)sychronized關(guān)鍵字定義的同步對(duì)象,我們一般稱(chēng)它為管程對(duì)象(Monitor),在后面我們還會(huì)對(duì)管程進(jìn)行詳細(xì)討論。在此不再多述。

3 同步測(cè)試

測(cè)試1.1.3.2中synchronized同步示例,為了達(dá)到測(cè)試的目的可以分別在臨界區(qū)A,B,C,D中加入延時(shí)操作Thread.sleep(3000)并輸出一些調(diào)試信息。這樣就可以得到可見(jiàn)的同步效果顯示了。測(cè)試代碼可以參看下面的清單:

/**
* 同步對(duì)象測(cè)試
* @author iangao
*/
public class SynchronizedObjectTest {
public static void main(String[] args){
// 定義要同步的兩段代碼
new ThreadsTest(){
private Foo foo=new Foo();
void runInThread1() { // <反射>
foo.f(); // 在線(xiàn)程1中執(zhí)行foo.f()
}// http://www.csdn.net/blog/Iangao
void runInThread2() { // <反射>
foo.g(); // 在線(xiàn)程2中執(zhí)行foo.g()
}// http://www.csdn.net/blog/Iangao
}.execute(2); // 執(zhí)行同步測(cè)試(啟動(dòng)2個(gè)線(xiàn)程)
}// http://www.csdn.net/blog/Iangao
} 測(cè)試結(jié)果:
[T1]: 準(zhǔn)備進(jìn)入: synObject臨界區(qū)A
[T1]: 進(jìn)入: synObject臨界區(qū)A
[T1]: <執(zhí)行: balance=balance+amount>
[T1]:
[T2]: 準(zhǔn)備進(jìn)入: synObject臨界區(qū)B //等待T1解鎖
[T1]: 離開(kāi): synObject臨界區(qū)A
[T2]: 進(jìn)入: synObject臨界區(qū)B //T1已解鎖
[T2]: <執(zhí)行: balance=balance-amount>
[T2]:
[T1]: <已離開(kāi)臨界區(qū),與T2并行>
[T1]: <結(jié)束>
[T2]: 離開(kāi): synObject臨界區(qū)B
[T2]: <結(jié)束>

4. 對(duì)象鎖與類(lèi)鎖

在Java中,用synchronized定義的都有兩種鎖,一個(gè)種是對(duì)象鎖(每個(gè)對(duì)象有一把鎖), 一種是類(lèi)鎖(每個(gè)class有一把鎖),前面討論的主要是對(duì)象鎖,下我們用一個(gè)例子來(lái)研究對(duì)象鎖與類(lèi)鎖的區(qū)別:

/**
* 類(lèi)鎖測(cè)試
* @author iangao
*/
public class ClassLockTest extends ThreadsTest{

public void runInThread1(){ g(); }
public void runInThread2(){ f(); }
// http://www.csdn.net/blog/Iangao
/**
* 同步的是類(lèi)鎖(class lock)
*/
public static synchronized void f(){
output("enter f");
sleep(1000);
output("leave f");
}// http://www.csdn.net/blog/Iangao
/**
* 同步的是對(duì)象鎖(object lock),
* f,g必須同時(shí)為static或非static同步才會(huì)成立
*/
public synchronized void g(){
output("enter g");
sleep(1000);// http://www.csdn.net/blog/Iangao
output("leave g");
}// http://www.csdn.net/blog/Iangao
public static void main(String[] args){
new ClassLockTest().execute(2);
}// http://www.csdn.net/blog/Iangao
}
執(zhí)行結(jié)果:
[T1]: enter g
[T2]: enter f
[T1]: leave g
[T2]: leave f

結(jié)論:

static方法定義的是類(lèi)鎖, 而非static方法定義的是對(duì)象鎖. 因?yàn)閮蓚€(gè)方法同步的不是同一個(gè)鎖,所以同步失效.

執(zhí)行結(jié)果2(把g改成static后的):
[T1]: enter g
[T1]: leave g
[T2]: enter f
[T2]: leave f

結(jié)論:

此時(shí)兩個(gè)方法都是同步的class鎖, 同步成功!

1.2.2 wait-notify機(jī)制

1.2.2.1 wait、notify簡(jiǎn)介

Java語(yǔ)言為我們提供了一套用于線(xiàn)程間同步的通信機(jī)制即wait-nofity機(jī)制。前面我們知道了,sychronized關(guān)鍵字可以讓我們把任何一個(gè)Object對(duì)象做為同步對(duì)象來(lái)看待,而Java為每個(gè)Object都實(shí)現(xiàn)了wait()和notify()方法。它們必須用在被sychronized同步的Object的臨界區(qū)內(nèi)。通過(guò)的wait()我們可以使得處于臨界區(qū)內(nèi)的線(xiàn)程進(jìn)入阻塞狀態(tài),同時(shí)釋放被同步對(duì)象的控制權(quán),而notify操作可以喚醒一個(gè)因調(diào)用了wait操作而處于阻塞狀態(tài)中的線(xiàn)程,使其進(jìn)入就緒狀態(tài)。被重新?lián)Q醒的線(xiàn)程會(huì)試圖重新獲得臨界區(qū)的控制權(quán),并繼續(xù)執(zhí)行臨界區(qū)內(nèi)wait之后面的代碼。如果發(fā)出notify操作時(shí)沒(méi)有處于阻塞狀態(tài)中的線(xiàn)程,那么該信號(hào)會(huì)被忽略.

/**
* Wait/Notify 機(jī)制測(cè)試
* @author iangao
*/// http://www.csdn.net/blog/Iangao
public class WaitNotifyTest {
public static void main(String[] args){
new ThreadsTest(){
Object obj=new Object();
void runInThread1()
throws InterruptedException{
waiter();
}// http://www.csdn.net/blog/Iangao
void runInThread2(){
sleep(100);
notifyer();
}// http://www.csdn.net/blog/Iangao
void runInThread3(){
sleep(1000);
notifyer();
}// http://www.csdn.net/blog/Iangao
void runInThread4()
throws InterruptedException{
sleep(6000);
waiter();
}// http://www.csdn.net/blog/Iangao
/**
* WAITER
*/
void waiter()
throws InterruptedException {
output("");
synchronized(obj){
output("enter");
int i=0;
for(;i<3;i++)
output(""+i,500);
output("wait...");
obj.wait();
output("back");
for(;i<5;i++)
output(""+i,100);
output("leave");
}
}// http://www.csdn.net/blog/Iangao
/**
* NOTIFYER
*/
void notifyer() {
output("");
synchronized(obj){
int i=0;
output("enter");
for(;i<2;i++)
output(""+i,1000);
output("notify");
obj.notify();
for(; i<4; i++)
output(""+i,100);
output("leave");
}
}// http://www.csdn.net/blog/Iangao
}.execute(4);
}// http://www.csdn.net/blog/Iangao
}// http://www.csdn.net/blog/Iangao
execute(2)執(zhí)行結(jié)果:
[T1]:
[T1]: enter
[T1]: 0... (0.5秒)
[T2]: [1]
[T1]: 1... (0.5秒)
[T1]: 2... (0.5秒)
[T1]: wait...
[T2]: enter [2]
[T2]: 0... (1.0秒)
[T2]: 1... (1.0秒)
[T2]: notify [3]
[T2]: 2... (0.1秒)
[T2]: 3... (0.1秒)
[T2]: leave
[T1]: back [4]
[T1]: 3... (0.1秒)
[T1]: 4... (0.1秒)
[T1]: leave
execute(4)執(zhí)行結(jié)果:
[T1]:
[T1]: enter
[T1]: 0... (0.5秒)
[T2]:
[T1]: 1... (0.5秒)
[T1]: 2... (0.5秒)
[T3]:
[T1]: wait... [1]
[T2]: enter
[T2]: 0... (1.0秒)
[T2]: 1... (1.0秒)
[T2]: notify [2]
[T2]: 2... (0.1秒)
[T2]: 3... (0.1秒)
[T2]: leave
[T3]: enter [3]
[T3]: 0... (1.0秒)
[T3]: 1... (1.0秒)
[T3]: notify [4]
[T3]: 2... (0.1秒)
[T3]: 3... (0.1秒)
[T3]: leave
[T1]: back [5]
[T1]: 3... (0.1秒)
[T4]:
[T1]: 4... (0.1秒)
[T1]: leave
[T4]: enter
[T4]: 0... (0.5秒)
[T4]: 1... (0.5秒)
[T4]: 2... (0.5秒)
[T4]: wait... [6]

分析:
T2要進(jìn)入臨界區(qū)時(shí)會(huì)由于T1掌控臨界區(qū)而等待。
wait()操作使得T1進(jìn)入了阻塞狀態(tài)并釋放了通過(guò)syncrhonized同步的對(duì)象obj的控制權(quán),這使得T2可以進(jìn)入臨界區(qū)
T2的notify()可以喚醒T1,但由于并不立即釋放對(duì)obj的控制權(quán), 因此這時(shí)的T1處于就緒狀態(tài)
T1直到T2退出臨界區(qū)后才重獲控制權(quán),并繼續(xù)后面的業(yè)務(wù)
分析:
T1 wait時(shí)雖然有T2,T3在等待,但也只能有一個(gè)線(xiàn)程進(jìn)入臨界區(qū).
由于在T2 notify之前T3已處于就緒狀態(tài)中,加上notify后的T1就有兩個(gè)處于就緒中的線(xiàn)程等待進(jìn)入臨界區(qū)了
在T2離開(kāi)臨界區(qū)時(shí),有可能被T3先搶到臨界區(qū),這時(shí)雖然T1已被T2喚醒,但仍要繼續(xù)等待。
T3發(fā)送notify信號(hào)時(shí),系統(tǒng)并沒(méi)有阻塞的線(xiàn)程,因此這個(gè)信號(hào)實(shí)際上根本沒(méi)起作用。
T1終于在T3結(jié)束后重獲了臨界區(qū)的控制權(quán),不過(guò)時(shí)這離T2的snotify操作已經(jīng)很久了。
T4的wait操作由于沒(méi)有notify來(lái)激活,因此它會(huì)一直等下去,至于先前T3的notify是不會(huì)對(duì)后面的wait起作用的。

通過(guò)上面一系列的測(cè)試與分析,我們可以得出一個(gè)得要結(jié)論,那就是“wait()對(duì)notify()的響應(yīng)很有可能是不及時(shí)的”,之所以強(qiáng)調(diào)這一點(diǎn)是因?yàn)樗鶗?huì)由于響應(yīng)不及時(shí)而造成響應(yīng)時(shí)的系統(tǒng)狀態(tài)與發(fā)出notify時(shí)的不一致,所以在實(shí)際應(yīng)用中我們要多加注意這一點(diǎn),尤其是在那些與狀態(tài)有關(guān)的同步應(yīng)用中這點(diǎn)尤為重要。

1.2.2.2 notify 與 notifyAll

notify的只能喚醒一個(gè)通過(guò)調(diào)用wait而等待的線(xiàn)程, notifyAll可以喚醒所有調(diào)用wait或因synchronized關(guān)鍵字而等待的線(xiàn)程. 不過(guò)通過(guò)notifyAll喚醒的所有線(xiàn)程也必須按照上節(jié)分析的過(guò)程,依次進(jìn)入臨界區(qū).

1.2.3 wait與sleep的比較

// http://www.csdn.net/blog/Iangao wait() sleep()
所屬對(duì)象 Object Thread
阻塞當(dāng)前線(xiàn)程 可以 可以
使用條件 必須在管程(Monitor)內(nèi)使用,即所屬Object必須已被sychronized同步。 隨時(shí)
管程(Monitor)內(nèi)使用效果
(synchronized臨界區(qū)內(nèi)) 釋放對(duì)管程對(duì)象(Monitor)的控制權(quán) 不釋放對(duì)管程對(duì)象(Monitor)控制權(quán)
喚醒 notify() 無(wú)

發(fā)表于 @ 2008年10月09日 11:52:00|評(píng)論(0)|收藏

新一篇: Java同步技術(shù)(二) |

本文來(lái)自CSDN博客,轉(zhuǎn)載請(qǐng)標(biāo)明出處:http://blog.csdn.net/Iangao/archive/2008/10/09/3041265.aspx

文章名稱(chēng):轉(zhuǎn):Java同步技術(shù)(一)
網(wǎng)頁(yè)URL:http://muchs.cn/article8/ihidip.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站排名、App設(shè)計(jì)、商城網(wǎng)站、網(wǎng)站收錄、靜態(tài)網(wǎng)站企業(yè)網(wǎng)站制作

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

h5響應(yīng)式網(wǎng)站建設(shè)