java 與操作系統同步問題(三)————父親兒子女兒水果問題


  問題描述:父親每次都會放一個水果在桌子上,女兒喜歡吃香蕉(只吃香蕉), 兒子喜歡吃蘋果(只吃蘋果)。父親每次只會隨機往桌子上放一個水果(蘋果或香蕉),兒子,女兒會來取。使用p、v操作來完成父親、兒子、女兒的同步行為模擬。

  問題分析:由上述描述我們可以知道,桌子就是一個緩沖區(單緩沖),同一時刻,只能有一個人對它進行放和取得操作。所以桌子就是一個互斥信號量。而桌子上有蘋果,且父親沒有放,兒子才能取,女兒也是同理。所以應該還有兩個資源信號量:1 蘋果 2 香蕉

在由題意分析可知,三個信號量的初始值應該為 1 0 0 因為桌子只能放一個水果。而在開始的時候,桌子上是空的(所以可以進行放的操作),所以蘋果、香蕉初始資源量都為空。

  代碼實現:

       1.信號量設定如下:

    /**
     * 緩沖區是否滿信號量
     */
    Semaphore empty;
    
    /**
     * 蘋果信號量
     */
    Semaphore apple;
    
    /**
     * 香蕉信號量
     */
    Semaphore banana;


empty = new Semaphore(1);
apple = new Semaphore(0);
banana = new Semaphore(0);

 

       2.父親的放的線程,只有在桌子互斥資源量可以用的時候才能進行放的操作。所以要先p一下桌子信號量。

       

Thread fatherThread = new Thread(new Runnable() {
        String className = "father";
        
        @Override
        public void run() {
            // TODO Auto-generated method stub
            while(true) {
                Semaphore.Wait(empty, className);
                if (randomAB()) {
                    System.out.println(className + "往盤子里放了一個蘋果");
                    Semaphore.Signal(apple, className);
                } else {
                    System.out.println(className + "往盤子里放了一個香蕉");
                    Semaphore.Signal(banana, className);
                }
                System.out.println(className + "完成了一次放的操作");
                //隨機生成休眠時間,代表放入產品的操作時間
                long millis = (long) (Math.random() * 1000);
                try {
                    Thread.sleep(millis);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                
                
            }
        }
    });

       3.兒子的實現,要判斷是否有蘋果,沒有的話就等待

    Thread sonThread = new Thread(new Runnable() {
        String className = "son";
        @Override
        public void run() {
            // TODO Auto-generated method stub
            while(true) {
                Semaphore.Wait(apple, className);
                System.out.println(className + "從盤子里取了一個蘋果");
                //隨機生成休眠時間,代表放入產品的操作時間
                long millis = (long) (Math.random() * 1000);
                try {
                    Thread.sleep(millis);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                System.out.println(className + "吃了一個蘋果");
                Semaphore.Signal(empty, className);
                System.out.println(className + "完成了一次取吃的操作");
            }
        }
    });

      4.女兒的代碼實現:原理跟兒子的類似

    Thread daughterThread = new Thread(new Runnable() {
        String className = "daughter";
        @Override
        public void run() {
            // TODO Auto-generated method stub
            while(true) {
                Semaphore.Wait(banana, className);
                System.out.println(className + "從盤子里取了一個香蕉");
                //隨機生成休眠時間,代表放入產品的操作時間
                long millis = (long) (Math.random() * 1000);
                try {
                    Thread.sleep(millis);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                System.out.println(className + "吃了一個香蕉");
                Semaphore.Signal(empty, className);
                System.out.println(className + "完成了一次取吃的操作");
            }
        }
    });

 

運行結果如下:

daughter被阻塞
son被阻塞
father往盤子里放了一個香蕉
father資源量足夠,喚醒一個
father完成了一次放的操作
daughter從盤子里取了一個香蕉
daughter吃了一個香蕉
daughter完成了一次取吃的操作
daughter被阻塞
father往盤子里放了一個香蕉
father資源量足夠,喚醒一個
father完成了一次放的操作
daughter從盤子里取了一個香蕉
father被阻塞
daughter吃了一個香蕉
daughter資源量足夠,喚醒一個
daughter完成了一次取吃的操作
....

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM