首页 > 代码库 > java 与操作系统进程同步问题(一)————互斥问题

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 =http://www.mamicode.com/ 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();
    }

 

测试结果

技术分享

java 与操作系统进程同步问题(一)————互斥问题