日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
Java并發(fā)編程之同步互斥問題

在操作系統(tǒng)中同步與互斥是一個(gè)重要問題,這里主要研究一下怎樣用Java來實(shí)現(xiàn)操作系統(tǒng)中的一些同步互斥算法。

創(chuàng)新互聯(lián)是一家專業(yè)提供永修企業(yè)網(wǎng)站建設(shè),專注與成都網(wǎng)站制作、成都網(wǎng)站設(shè)計(jì)、H5場景定制、小程序制作等業(yè)務(wù)。10年已為永修眾多企業(yè)、政府機(jī)構(gòu)等服務(wù)。創(chuàng)新互聯(lián)專業(yè)網(wǎng)站設(shè)計(jì)公司優(yōu)惠進(jìn)行中。

1、軟件實(shí)現(xiàn)臨界區(qū)域問題

在《操作系統(tǒng)概念(第七版)》中,7.2討論了臨界區(qū)域問題,下面給出算法和Java實(shí)現(xiàn)代碼。

1.1 算法2

算法2的偽代碼如下:

 
 
 
  1. do{  
  2.  flag[i]=true;  
  3.  while(flag[j]);  
  4.  臨界區(qū);  
  5.  flag[i]=false;  
  6.  剩余區(qū);  
  7. }while(1) 

Java實(shí)現(xiàn)代碼如下:

 
 
 
  1. package mutiple_thread;  
  2.  
  3. public class OS_SYN_A2{  
  4.     public static  int flag[]=new int [3];  
  5.     public static int cnt=0;  
  6.     public static void main(String args[]){  
  7.         class proo implements Runnable{  
  8.             public proo(){  
  9.                   
  10.             }  
  11.             @Override 
  12.             public void run() {  
  13.                 // TODO Auto-generated method stub  
  14.                 while(true){  
  15.                     flag[1]=1;  
  16.                     while(flag[2]==1){  
  17.                           
  18.                     }  
  19.                     if(cnt==5){  
  20.                         flag[1]=0;  
  21.                     }else{  
  22.                         cnt++;  
  23.                         System.out.println("pro ++! now id"+cnt);  
  24.                         flag[1]=0;  
  25.                     }  
  26.                 }  
  27.             }  
  28.               
  29.         }  
  30.  
  31.         class conn implements Runnable{  
  32.  
  33.             @Override 
  34.             public void run() {  
  35.                 // TODO Auto-generated method stub  
  36.                 while(true){  
  37.                     flag[2]=1;  
  38.                     while(flag[1]==1){  
  39.                           
  40.                     }  
  41.                     //臨界區(qū)  
  42.                     if(cnt==0){  
  43.                         flag[2]=0;  
  44.                     }else{  
  45.                         cnt--;  
  46.                         System.out.println("con --! now id"+cnt);  
  47.                         //退出臨界區(qū)  
  48.                         flag[2]=0;  
  49.                     }  
  50.                 }  
  51.             }  
  52.         }  
  53.         new Thread(new proo()).start();  
  54.         new Thread(new conn()).start();  
  55.     }  
  56.       

這個(gè)算法的主要思路是通過設(shè)置flag來確定執(zhí)行哪個(gè)線程,但是可能會(huì)造成饑餓,因此不行。

1.2 算法3

算法3通過共享兩個(gè)變量 flag 和turn來實(shí)現(xiàn)同步。

 
 
 
  1. package mutiple_thread;  
  2.  
  3. public class OS_SYN_A3{  
  4.     public static  int flag[]=new int [3];  
  5.     public static int turn=0;  
  6.     public static int cnt=0;  
  7.     public static void main(String args[]){  
  8.         class proo implements Runnable{  
  9.             public proo(){  
  10.                   
  11.             }  
  12.             @Override 
  13.             public void run() {  
  14.                 // TODO Auto-generated method stub  
  15.                 while(true){  
  16.                     flag[1]=1;  
  17.                     turn=2;  
  18.                     while(flag[2]==1&&turn==2){  
  19.                           
  20.                     }  
  21.                     if(cnt==5){  
  22.                         flag[1]=0;  
  23.                     }else{  
  24.                         cnt++;  
  25.                         System.out.println("pro ++! now id"+cnt);  
  26.                         flag[1]=0;  
  27.                     }  
  28.                 }  
  29.             }  
  30.               
  31.         }  
  32.  
  33.         class conn implements Runnable{  
  34.  
  35.             @Override 
  36.             public void run() {  
  37.                 // TODO Auto-generated method stub  
  38.                 while(true){  
  39.                     flag[2]=1;  
  40.                     turn=1;  
  41.                     while(flag[1]==1&&turn==1){  
  42.                           
  43.                     }  
  44.                     //臨界區(qū)  
  45.                     if(cnt==0){  
  46.                         flag[2]=0;  
  47.                     }else{  
  48.                         cnt--;  
  49.                         System.out.println("con --! now id"+cnt);  
  50.                         //退出臨界區(qū)  
  51.                         flag[2]=0;  
  52.                     }  
  53.                 }  
  54.             }  
  55.         }  
  56.         new Thread(new proo()).start();  
  57.         new Thread(new conn()).start();  
  58.     }  
  59.       

這是一種正確的軟件實(shí)現(xiàn)方法。

2、經(jīng)典同步問題的Java實(shí)現(xiàn)

2.1 讀者寫者問題

這里實(shí)現(xiàn)的讀者優(yōu)先的算法,使用了Java并發(fā)包的信號(hào)量來實(shí)現(xiàn)。

實(shí)現(xiàn)的偽代碼如下:

讀者進(jìn)程:

 
 
 
  1. while(1){  
  2.  wait(mutex)  
  3.    count++;  
  4.    if(readercount==1){  
  5.    wait(writer);   
  6.  }  
  7. signal(mutex);  
  8. do reading;  
  9. wait(mutex);  
  10. cnt--;  
  11. if(cnt==0){  
  12.   signal(writer);  
  13. }  
  14. signal(mutex);  
  15. }  
  16. }

算法通過共享writer和mutex兩個(gè)信號(hào)量,來處理同步問題

 
 
 
  1. package mutiple_thread;  
  2.  
  3. import java.util.concurrent.Semaphore;  
  4.  
  5. public class OS_Readerwriter{  
  6.     static Semaphore sem=new Semaphore(1);  
  7.     static Semaphore sem_wrt=new Semaphore(1);  
  8.     static int readercount=0;  
  9.     static String a="hahaha";  
  10.     public static void main(String args[]){  
  11.         class reader implements Runnable{  
  12.             public reader(){  
  13.                   
  14.             }  
  15.             @Override 
  16.             public void run() {  
  17.                 // TODO Auto-generated method stub  
  18.                 try {  
  19.                     sem.acquire();  
  20.                     readercount++;  
  21.                 } catch (InterruptedException e) {  
  22.                     // TODO Auto-generated catch block  
  23.                     e.printStackTrace();  
  24.                 }  
  25.                 if(readercount==1){  
  26.                     try {  
  27.                         sem_wrt.acquire();  
  28.                     } catch (InterruptedException e) {  
  29.                         // TODO Auto-generated catch block  
  30.                         e.printStackTrace();  
  31.                     }  
  32.                 }  
  33.                 sem.release();  
  34.                   
  35.                 System.out.println("Reading "+a);  
  36.                   
  37.                 try {  
  38.                     sem.acquire();  
  39.                 } catch (InterruptedException e) {  
  40.                     // TODO Auto-generated catch block  
  41.                     e.printStackTrace();  
  42.                 }  
  43.                 readercount--;  
  44.                 if(readercount==0){  
  45.                     sem_wrt.release();  
  46.                 }  
  47.                 sem.release();  
  48.             }  
  49.         }  
  50.           
  51.         class writer implements Runnable{  
  52.             public writer(){  
  53.                   
  54.             }  
  55.             @Override 
  56.             public void run() {  
  57.                 // TODO Auto-generated method stub  
  58.                 try {  
  59.                     sem_wrt.acquire();  
  60.                 } catch (InterruptedException e) {  
  61.                     // TODO Auto-generated catch block  
  62.                     e.printStackTrace();  
  63.                 }  
  64.                 a=a+"abc";  
  65.                 System.out.println("Writing "+a);  
  66.                 sem_wrt.release();  
  67.             }  
  68.               
  69.         }  
  70.         for(int i=1;i<=10;i++){  
  71.             new Thread(new writer()).start();  
  72.             new Thread(new reader()).start();  
  73.         }  
  74.           
  75.     }  

2.2 哲學(xué)家問題

算法思路:通過對(duì)每一只筷子設(shè)置信號(hào)量,來進(jìn)行同步判斷。

Java實(shí)現(xiàn)代碼如下:

 
 
 
  1. package mutiple_thread;  
  2.  
  3. import java.util.concurrent.Semaphore;  
  4.  
  5. public class OS_Philosopher{  
  6.     static int chop[]=new int [7];  
  7.     static Semaphore []sem=new Semaphore[7];  
  8.       
  9.     public static void main(String args[]) throws InterruptedException{  
  10.         for(int i=0;i<=6;i++){  
  11.             sem[i]=new Semaphore(1);  
  12.         }  
  13.         Thread.sleep(1000);  
  14.         class philosopher implements Runnable{  
  15.             int i;  
  16.             public philosopher(int i){  
  17.                 this.i=i;  
  18.             }  
  19.  
  20.             @Override 
  21.             public void run() {  
  22.                 // TODO Auto-generated method stub  
  23.                 while(true){  
  24.                     try {  
  25.                         synchronized(this){  
  26.                             sem[i].acquire();  
  27.                             sem[(i+1)%5].acquire();  
  28.                         }  
  29.                           
  30.                     } catch (InterruptedException e) {  
  31.                         // TODO Auto-generated catch block  
  32.                         e.printStackTrace();  
  33.                     }  
  34.                     System.out.println("Phi"+i+" is Eating");  
  35.                     //sleep();  
  36.                     try {  
  37.                         Thread.sleep(1);  
  38.                     } catch (InterruptedException e) {  
  39.                         // TODO Auto-generated catch block  
  40.                         e.printStackTrace();  
  41.                     }  
  42.                     sem[i].release();  
  43.                     sem[(i+1)%5].release();  
  44.                     System.out.println("Phi"+i+" is Thinking");  
  45.                     //sleep();  
  46.                     try {  
  47.                         Thread.sleep(1);  
  48.                     } catch (InterruptedException e) {  
  49.                         // TODO Auto-generated catch block  
  50.                         e.printStackTrace();  
  51.                     }  
  52.                 }  
  53.             }  
  54.         }  
  55.         philosopher t1=new philosopher(1);  
  56.         philosopher t2=new philosopher(2);  
  57.         philosopher t3=new philosopher(3);  
  58.         philosopher t4=new philosopher(4);  
  59.         philosopher t5=new philosopher(5);  
  60.         new Thread(t1).start();  
  61.         new Thread(t2).start();  
  62.         new Thread(t3).start();  
  63.         new Thread(t4).start();  
  64.         new Thread(t5).start();  
  65.           
  66.     }  

2.3 理發(fā)店問題:

理發(fā)店理有一位理發(fā)師、一把理發(fā)椅和 5 把供等候理發(fā)的顧客坐的椅 子。如果沒有顧客,理發(fā)師便在理發(fā)椅上睡覺。一個(gè)顧客到來時(shí),它必須叫 醒理發(fā)師。如果理發(fā)師正在理發(fā)時(shí)又有顧客來到,則如果有空椅子可坐,就 坐下來等待,否則就離開。

算法思路如下:采用信號(hào)量進(jìn)行判斷。初始值為1,即是有一個(gè)理發(fā)師在服務(wù)。

實(shí)現(xiàn)代碼如下:

 
 
 
  1. package mutiple_thread;  
  2.  
  3. import java.util.concurrent.Semaphore;  
  4.  
  5. public class OS_Barber1{  
  6.     static int cnt = 0;  
  7.     static int MAX = 5;  
  8.     static int busy = 0;  
  9.     static Semaphore sem=new Semaphore(1);  
  10.     public static void main(String args[]) throws InterruptedException{  
  11.         OS_Barber1 bar=new OS_Barber1();  
  12.         for(int i=1;i<=20;i++){  
  13.             new Thread(new Bar1(bar,i)).start();  
  14.             Thread.sleep((int) (400 - Math.random() * 300));  
  15.         }  
  16.     }  
  17.     public synchronized boolean isFull() {  
  18.         if (cnt == MAX) {  
  19.             return true;  
  20.         }  
  21.         return false;  
  22.     }  
  23.  
  24.     public synchronized boolean isEmpty() {  
  25.         if (cnt == 0) {  
  26.             return true;  
  27.         }  
  28.         return false;  
  29.     }  
  30.  
  31.     public synchronized boolean isBusy() {  
  32.         if (busy == 1) {  
  33.             return true;  
  34.         }  
  35.         return false;  
  36.     }  
  37.       
  38.     public  void Gobar(int index) throws InterruptedException{  
  39.           
  40.           
  41.         System.out.println("Con"+index+" is coming");  
  42.         cnt++;  
  43.         //判斷是否滿  
  44.         if(isFull()){  
  45.             System.out.println("Is full,"+"Con"+index+" is leaving");  
  46.             cnt--;  
  47.         }else{  
  48.             if(busy==1){  
  49.                 System.out.println("Con"+index+" is waitting");  
  50.             }  
  51.             //sem.acquire();  
  52.             synchronized (this){  
  53.                 while(busy==1){  
  54.                     //若有人在理發(fā),則等待  
  55.                     wait();  
  56.                 }  
  57.             }  
  58.               
  59.             if(cnt==1){  
  60.                 System.out.println("Con"+index+" is wake");  
  61.             }  
  62.             busy=1;  
  63.             System.out.println("Con"+index+" is Serving");  
  64.             Thread.sleep(1000);  
  65.             System.out.println("Con"+index+" is leaving");  
  66.             cnt--;  
  67.             //sem.release();  
  68.             synchronized (this){  
  69.                 busy=0;  
  70.                 //喚醒  
  71.                 notify();  
  72.             }  
  73.             if(cnt==0){  
  74.                 System.out.println("Bar is sleep");  
  75.             }  
  76.         }  
  77.     }  
  78. }  
  79. class Bar1 implements Runnable {  
  80.     OS_Barber1 ob;  
  81.     int index;  
  82.     public Bar1(OS_Barber1 ob,int i) {  
  83.         this.ob = ob;  
  84.         index=i;  
  85.     }  
  86.  
  87.     @Override 
  88.     public void run() {  
  89.         // TODO Auto-generated method stub  
  90.         try {  
  91.             ob.Gobar(index);  
  92.         } catch (InterruptedException e) {  
  93.             // TODO Auto-generated catch block  
  94.             e.printStackTrace();  
  95.         }  
  96.     }  
  97.  

在算法中我使用了wait(),notify()來實(shí)現(xiàn),也可以使用信號(hào)量來實(shí)現(xiàn),注釋部分就是使用信號(hào)量的實(shí)現(xiàn)。

在實(shí)現(xiàn)過程中,我發(fā)現(xiàn)了一些問題,也就是下面要討論的wait() 和notify() 和notifyAll()

3、 wait() ,notify() 和notifyAll()

synchronized 方法控制對(duì)類成員變量的訪問:每個(gè)類實(shí)例對(duì)應(yīng)一把鎖,每個(gè) synchronized 方法都必須獲得調(diào)用該方法的類實(shí)例的鎖方能執(zhí)行,否則所屬線程阻塞,方法一旦執(zhí)行,就獨(dú)占該鎖,直到從該方法返回時(shí)才將鎖釋放,此后被阻塞的線程方能獲得該鎖,重新進(jìn)入可執(zhí)行狀態(tài)。

wait()/notify():調(diào)用任意對(duì)象的 wait() 方法導(dǎo)致線程阻塞,并且該對(duì)象上的鎖被釋放。而調(diào)用 任意對(duì)象的notify()方法則導(dǎo)致因調(diào)用該對(duì)象的 wait() 方法而阻塞的線程中隨機(jī)選擇的一個(gè)解除阻塞(但要等到獲得鎖后才真正可執(zhí)行)。

synchronized和wait()、notify()的關(guān)系

1.有synchronized的地方不一定有wait,notify

2.有wait,notify的地方必有synchronized.這是因?yàn)閣ait和notify不是屬于線程類,而是每一個(gè)對(duì)象都具有的方法,而且,這兩個(gè)方法都和對(duì)象鎖有關(guān),有鎖的地方,必有synchronized。

另外,請(qǐng)注意一點(diǎn):如果要把notify和wait方法放在一起用的話,必須先調(diào)用notify后調(diào)用wait,因?yàn)槿绻{(diào)用完wait,該線程就已經(jīng)不是current thread了。

注:調(diào)用wait()方法前的判斷***用while,而不用if;while可以實(shí)現(xiàn)被wakeup后thread再次作條件判斷;而if則只能判斷一次;

線程的四種狀態(tài)

  1. 新狀態(tài):線程已被創(chuàng)建但尚未執(zhí)行(start() 尚未被調(diào)用)。
  2. 可執(zhí)行狀態(tài):線程可以執(zhí)行,雖然不一定正在執(zhí)行。CPU 時(shí)間隨時(shí)可能被分配給該線程,從而使得它執(zhí)行。
  3. 死亡狀態(tài):正常情況下 run() 返回使得線程死亡。調(diào)用 stop()或 destroy() 亦有同樣效果,但是不被推薦,前者會(huì)產(chǎn)生異常,后者是強(qiáng)制終止,不會(huì)釋放鎖。
  4. 阻塞狀態(tài):線程不會(huì)被分配 CPU 時(shí)間,無法執(zhí)行。

首先,前面敘述的所有方法都隸屬于 Thread 類,但是這一對(duì) (wait()/notify()) 卻直接隸屬于 Object 類,也就是說,所有對(duì)象都擁有這一對(duì)方法。初看起來這十分不可思議,但是實(shí)際上卻是很自然的,因?yàn)檫@一對(duì)方法阻塞時(shí)要釋放占用的鎖,而鎖是任何對(duì)象都具有的,調(diào)用任意對(duì)象的 wait() 方法導(dǎo)致線程阻塞,并且該對(duì)象上的鎖被釋放。而調(diào)用 任意對(duì)象的notify()方法則導(dǎo)致因調(diào)用該對(duì)象的 wait() 方法而阻塞的線程中隨機(jī)選擇的一個(gè)解除阻塞(但要等到獲得鎖后才真正可執(zhí)行)。

其次,前面敘述的所有方法都可在任何位置調(diào)用,但是這一對(duì)方法卻必須在 synchronized 方法或塊中調(diào)用,理由也很簡單,只有在synchronized 方法或塊中當(dāng)前線程才占有鎖,才有鎖可以釋放。

同樣的道理,調(diào)用這一對(duì)方法的對(duì)象上的鎖必須為當(dāng)前線程所擁有,這樣才有鎖可以釋放。因此,這一對(duì)方法調(diào)用必須放置在這樣的synchronized 方法或塊中,該方法或塊的上鎖對(duì)象就是調(diào)用這一對(duì)方法的對(duì)象。若不滿足這一條件,則程序雖然仍能編譯,但在運(yùn)行時(shí)會(huì)出現(xiàn)IllegalMonitorStateException 異常。

wait() 和 notify() 方法的上述特性決定了它們經(jīng)常和synchronized 方法或塊一起使用,將它們和操作系統(tǒng)的進(jìn)程間通信機(jī)制作一個(gè)比較就會(huì)發(fā)現(xiàn)它們的相似性:synchronized方法或塊提供了類似于操作系統(tǒng)原語的功能,它們的執(zhí)行不會(huì)受到多線程機(jī)制的干擾,而這一對(duì)方法則相當(dāng)于 block 和wakeup 原語(這一對(duì)方法均聲明為 synchronized)。它們的結(jié)合使得我們可以實(shí)現(xiàn)操作系統(tǒng)上一系列精妙的進(jìn)程間通信的算法(如信號(hào)量算法),并用于解決各種復(fù)雜的線程間通信問題。關(guān)于

wait() 和 notify() 方法***再說明兩點(diǎn):

***:調(diào)用 notify() 方法導(dǎo)致解除阻塞的線程是從因調(diào)用該對(duì)象的 wait() 方法而阻塞的線程中隨機(jī)選取的,我們無法預(yù)料哪一個(gè)線程將會(huì)被選擇,所以編程時(shí)要特別小心,避免因這種不確定性而產(chǎn)生問題。

第二:除了 notify(),還有一個(gè)方法 notifyAll() 也可起到類似作用,唯一的區(qū)別在于,調(diào)用 notifyAll() 方法將把因調(diào)用該對(duì)象的wait() 方法而阻塞的所有線程一次性全部解除阻塞。當(dāng)然,只有獲得鎖的那一個(gè)線程才能進(jìn)入可執(zhí)行狀態(tài)。

談到阻塞,就不能不談一談死鎖,略一分析就能發(fā)現(xiàn),suspend() 方法和不指
網(wǎng)站欄目:Java并發(fā)編程之同步互斥問題
文章出自:http://www.dlmjj.cn/article/dpdegge.html