當各個(gè)線(xiàn)程可以獨立進(jìn)行操作,也就是他們在執行期間并不共享數據時(shí),多線(xiàn)程編程是容易實(shí)現的。當幾個(gè)線(xiàn)程能夠訪(fǎng)問(wèn)和修改相同的數據時(shí),程序就潛在的出現不正確行為的可能性。
java中使用了一種易用的機制來(lái)防治線(xiàn)程沖突,即對需要訪(fǎng)問(wèn)共享數據的方法聲明為synchronized(同步)。
在同步方法中,在某一時(shí)刻只有一個(gè)線(xiàn)程允許執行代碼,所有其他線(xiàn)程必須等待。一個(gè)執行同步方法的線(xiàn)程對于要訪(fǎng)問(wèn)的那個(gè)對象,獲得鎖。當這個(gè)同步方法執行完成之后,這個(gè)線(xiàn)程釋放對象的鎖。在任何時(shí)刻,只有一個(gè)線(xiàn)程可以在一個(gè)對象上加鎖。因此,當一個(gè)線(xiàn)程擁有一個(gè)對象的鎖時(shí),這個(gè)對象就不能由其他線(xiàn)程訪(fǎng)問(wèn)--即使是通過(guò)這個(gè)對象定義的其他的方法。話(huà)句話(huà)說(shuō),如果一個(gè)對象擁有幾個(gè)同步方法,在任何時(shí)刻,只有其中一個(gè)方法能夠處于活動(dòng)狀態(tài)。正在執行這個(gè)類(lèi)的一個(gè)同步靜態(tài)方法的那個(gè)線(xiàn)程將獲得這個(gè)類(lèi)對象的一個(gè)鎖。
加鎖是在監視器的幫助下實(shí)現的。具有一個(gè)同步實(shí)例方法的每個(gè)對象,都擁有一個(gè)與之相關(guān)聯(lián)的監視器。同樣,具有一個(gè)同步靜態(tài)方法的每個(gè)類(lèi)也具有一個(gè)監視器。一個(gè)線(xiàn)程可以通過(guò)執行一個(gè)對象的其中一個(gè)同步方法成為這個(gè)對象的監視其的所有者。當一個(gè)線(xiàn)程完成了這個(gè)同步方法的執行之后,他就會(huì )移交監視器的所有權,這樣其他線(xiàn)程就可以取得這個(gè)所有權。線(xiàn)程同步是在一個(gè)監視器對象的幫助下實(shí)現的,他維護了一個(gè)列表,其中包括了所有等待執行他的任何同步方法的線(xiàn)程。在每一時(shí)刻,監視器只允許一個(gè)等待的線(xiàn)程進(jìn)行方法。
下面說(shuō)明一個(gè)I/O操作的同步實(shí)例代碼:
///////////////DataFile類(lèi)//////////////////////
class DataFile{
public DataFile(){
try{
FileIO.writeOneString("hello","hello.dat");
}catch(FileIOException e){}
}
synchronized void fileIO(){
try{
String str=FileIO.readOneString("hell.dat");
FileIO.writeOneString(str,"hello.dat");
}catch(FileIOException e){}
}
}
//////////////////ThreadFileIO類(lèi)/////////////////////////
class ThreadFileIO extends Thread{
DataFile df;
ThreadFileIO(String threadName,DataFile d){
df=d;
setName(threadName);
start();
}
public void run(){
int i=0;
while(i++<4){
try{
df.fileIO();
String str=FileIO.readOneString("hello.dat");
System.out.println(getName()+": "+"hello.dat contains:"+str);
sleep(5);
}catch(FileIOException e){}
catch(InterruptedException e){}
}
}
}
//////////////////////SynFileIO類(lèi)///////////////////////
public class SynFileIO {
public static void main(String[] args){
DataFile dd=new DataFile();
new ThreadFileIO("T0",dd);
new ThreadFileIO("t1",dd);
new ThreadFileIO("t2",dd);
new ThreadFileIO("t2",dd);
}
}
說(shuō)明:1、加入去掉代碼中的綠色字體,看看運行結果會(huì )有什么不同?
2、我們可以使用下面的語(yǔ)法只對一個(gè)代碼塊進(jìn)行同步:
synchronized(obj){
////代碼
}
其中obj就是加鎖的對象。當一個(gè)類(lèi)的靜態(tài)成員需要使用同步保護措施時(shí),我們需要把這個(gè)類(lèi)本身作為參數提供給synchronized。
本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請
點(diǎn)擊舉報。