/* * 讀者寫者問題 * * */import java.util.concurrent.locks.*;class Buffer {public int buffer[]=new int [10];//用於標識共用的緩衝區public boolean flag=false;//用於標識緩衝區的狀態public int i;//表示向緩衝區寫的位置 }class Writer implements Runnable //可能會有多個讀{private Buffer buffer;public Writer(Buffer buffer){this.buffer=buffer;}public void run(){while(true)//用迴圈表示不停地向裡面寫東西{synchronized(buffer)//這裡面是同步代碼塊,裡面都是對共用資料的操作,只能有一個線程操作{while(buffer.flag)//如果共用資料flag=true,表示共用資料區塊裡面已經寫入資料還沒有被讀出來,如果再寫的話,就要等待,這也是控制讀一次寫一次的關鍵try{buffer.wait();}catch(Exception ex) {}buffer.buffer[buffer.i]=buffer.i;//這裡面是向緩衝區裡面寫入資料的操作buffer.i=((buffer.i+1)%buffer.buffer.length);//防止資料的溢出buffer.flag=true;buffer.notifyAll();}try {Thread.sleep(100);}catch(Exception ex) {}}}}class Reader implements Runnable{private Buffer buffer;public Reader(Buffer buffer){this. buffer=buffer;}public void run(){while(true) //表示 讀者不停在進行讀操作{synchronized(buffer){while(!buffer.flag)try{buffer.wait();}catch(Exception ex) {}for(int i=0;i<buffer.i;i++){ System.out.print(buffer.buffer[i]);} System.out.println();buffer.flag=false;buffer.notifyAll();}try {Thread.sleep(100);}catch(Exception ex) {} //這句話沒有什麼意思,只是為了讓輸出會慢一點,在這個程式裡面沒有其他作用,加不加都一個樣}}}public class ReaderandWriter {public static void main(String args[]){Buffer buffer=new Buffer();Thread t1=new Thread(new Writer(buffer));Thread t2=new Thread(new Writer(buffer));Thread t3=new Thread(new Reader(buffer));Thread t4=new Thread(new Reader(buffer));t1.start();//t2.start();t3.start();t4.start();}}/* * 上面的程式在只有一個讀者和一個寫者的情況 下沒有任何錯誤,寫者沒寫進一個資料,讀者就讀取資料一次 * 而在實際中,線程的個數可能會有很多種,在有多個讀者和多個寫者的情況下,上面的代碼又會現在一個新的問題--- * 那就是在寫一個而讀多次,或者是讀一次而寫多次,這將會出現安全性問題,下面我們討論一下為什麼出現這種問題 * 假設現在有兩個讀者和兩個寫者,現在執行的線程是讀者,兩個寫者wait 中,讀者執行完後喚醒其中的一個寫者,然後寫者開始執行 * 當寫者執行完成後,下面又開始要喚醒線程,因為上面的兩個讀線程和一個寫線程都在等待當中,如果喚醒的是再是寫線程,因為裡面用的是 * if(buffer.flag) 這個在wait 之前就已經判斷過了,所以會直接執行下面的語句,那麼就是在讀了一次的情況下,而串連寫了兩次,如果寫的線程更多 的話, * 那麼就會出現更多 的問題,所以上面的if(buffer.flag)要改成while(buufer.flag) buffer.notify 要改成buffer.notifyAll();這樣就正確了 * * * 上面的程式由於由whiie(flag) notifyAll 控制,所以,無論 寫者線程或讀者線程有多少個,無論是否相同,它們都將遵守讀一個寫一個的順序了 * * 2011/10/24 19:21:45 * * * */