java 與操作系統進程同步問題(一)————互斥問題


  最近學校開設了操作系統原理課程,老師要求用任意語言去模擬進程的同步和互斥問題。

  在嘗試的寫了之后,發現這個問題非常有意思,故想記錄在博客中,作為自己的學習軌跡。

 

  個人還是比較喜歡用Java語言,所以采用了java來編寫。今天記錄的是多個進程訪問互斥資源量的問題,互斥即是某一資源同一時刻,只允許一個進程訪問,在離散數學中,對互斥定義如下

事件A和B的交集為空,A與B就是互斥事件,也叫互不相容事件。也可敘述為:不可能同時發生的事件。如A∩B為不可能事件(A∩B=Φ),那么稱事件A與事件B互斥,其含義是:事件A與事件B在任何一次試驗中不會同時發生(百度百科)。

如日常生活中的打印機,就是一個公共資源,同一時刻,只允許一個任務進行,其他任務排隊等待。

  采用記錄型信號量來實現。

 

  相應的wait(Semaphore s) (wait操作就是p操作,我們的課本里是這種叫法)的偽代碼就是

 

1 wait(Semaphore *s){
2      s->value--;         //value是資源個數
3      if(s->value < 0){
4           block(s->list);       //list是PCB(process_control_block)塊
5      }
6 }    

 

對應的signal(signal就是v操作)的偽代碼就是:

signal(Semaphore *s){
       s->value++;
       if(s->value >= 0)
             wakeup(s->list);
}

 

 

所以首先我們得實現一個信號量類,采用synchronized塊來模擬wait和signal操作 ,具體synchronized的細節請自行百度或者查閱其他博客園的文章,我理解的也不是特別透徹。

 

public class Semaphore {
    public Object lock = new Object();          //synchronized鎖住的是對象
    public  int value;                   //資源個數
    
    public Semaphore(int value) {
        this.value = value;
    }
}

 

在該類中我們實現wait和signal方法

 

    public static  void Wait(Semaphore semaphore,String className) {        //classname用來判斷是那個線程
        synchronized (semaphore.lock) {
            semaphore.value--;
            if (semaphore.value < 0)
            {
                try {
                    System.out.println(className + "被阻塞");
                    semaphore.lock.wait();
            
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
        
            
    }
    
    public static  void Signal(Semaphore semaphore,String className){
        synchronized (semaphore.lock) {
            semaphore.value++;
            if (semaphore.value <= 0) {
                System.out.println(className + "資源量足夠,喚醒一個");
                semaphore.lock.notify();
            }
        }
        
    }    

可以看到跟最開始的偽代碼基本思想都是一樣的。

 

到此,我們就已經完成了記錄型信號量。

 

下面我們就用記錄型信號量來完成互斥關系

首先給出用記錄型信號量完成互斥關系的偽代碼

 

operation()
{
     while(1){
        wait(mutex);
        //進入臨界區
        signal(mutex);
        //剩余區
    }
}    

 

臨界區:就是進程中訪問臨界資源的代碼

 

我們模擬多個人使用打印機來模擬進程互斥問題。

一般解決同步問題要先確定信號量,互斥信號量非常好確定,就是打印機,我們可以設初始打印機資源為1

 

首先完成一個Runnable的子類,它就是對打印機進行的操作,即為上述的operation

public class PrinterUser implements Runnable{
    //打印機信號量
    Semaphore printer;
  //確認線程身份 String userName;
public PrinterUser(Semaphore printer,String userName) { // TODO 自動生成的構造函數存根 this.printer = printer; this.userName = userName; } @Override public void run() { // TODO 自動生成的方法存根 while(true){ Semaphore.Wait(printer, userName); System.out.println("正在打印"); Semaphore.Signal(printer, userName); System.out.println(userName+"打印完成"); } } }

 

給出測試

public static void main(String[] args) {
        Semaphore printer = new Semaphore(1);
        // TODO Auto-generated method stub
        Thread threada= new Thread(new PrinterUser(printer, "打印者1"));
        Thread threadb= new Thread(new PrinterUser(printer, "打印者2"));
        
        threada.start();threadb.start();
    }

 

測試結果


免責聲明!

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



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