操作系统中的信号量实现互斥(java实现)

 在学习操作系统这本书的时候,我们使用的是汤小丹老师的《计算机操作系统》接下来我将会使用java语言去实现内部代码。

信号量操作

为使多个进程能互斥地访问某临界资源,只需为该资源设置一互斥信号量 mutex, 并设其初始值为1,然后将各进程访问该资源的临界区cs置于wait(mutex)和 signa(mutex)操作之间即可。这样,每个欲访问该临界资源的进程在进入临界区之前,都要先对mutex执行wait操作,若该资源此刻未被访问,本次wait操作必然成功,进程便可进入自己的临界区,这时若再有其它进程也欲进入自己的临界区,由于对mutex执行wait操作定会失败,因而此时该进程阻塞,从而保证了该临界资源能被互斥地访问。当访问临界资源的进程退出临界区后,又应对mutex执行signal操作,以便释放该临界资源。利用信号量实现两个进程互斥的描述如下:

设mutex为互斥信号量,其初值为1,取值范围为(-1, 0, 1)。 当mutex=1时,表示两个进程皆未进入需要互斥的临界区;当mutex=0时,表示有一个进程进入临界区运行,另外-一个必须等待,挂入阻塞队列;当mutex=-1时,表示有一个进程正在临界区运行,另外一个进程因等待而阻塞在信号量队列中,需要被当前已在临界区运行的进程退出时唤醒。

下面为伪代码:

semaphore mutex =1;
Pa(){
    while(1){
        wait(mutex);
        //临界区
        singal(mutex);
        //剩余区
    }
}

在利用信号量机制实现进程互斥时应该注意Bavait(mutex)和signl(mutex)必须成对地出现。缺少witmtx)将会导致系统混乱,不能保证对临界资源的互斥访问;而缺少spgal(mutx)将会使临界资源永远不被释放,从而使因等待该资源而阻塞的进程不能被唤醒。

接下来为java语言描述。

package chapter02;

public class P62Mutex {
    //mutex为1的时候:没有线程进入临界区
    //mutex为0的时候:有一个线程进入临界区
    //mutex为-1的时候:即另外一个线程进入临界区,但是需要等待
    private static int mutex = 1;

    public static void main(String[] args) {
        InnerThread thead1 = new InnerThread();
        thead1.setName("线程1");
        thead1.start();

        InnerThread thead2 = new InnerThread();
        thead2.setName("线程2");
        thead2.start();
    }

    static class InnerThread extends Thread {

        @Override
        public void run() {
            while (true) {

                if (mutex >=0) {
                    //wait操作
                    mutex--;
                    //临界区
                    try {
                        System.out.println(this.getName() + "已经进入线程中");
                        Thread.sleep(10);
                        //signal操作
                        mutex++;
                        System.out.println(this.getName() + "完成操作,释放信号量");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } else {
                    try {
                        System.out.println("当前已经有线程进入了临界区,"+this.getName()+"线程等待");
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                try {
                    //时间片流转
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

实验现象:

"C:\Program Files\Java\jdk1.8.0_101\bin\java.exe"
线程1已经进入线程中
线程2已经进入线程中
线程2完成操作,释放信号量
线程1完成操作,释放信号量
线程2已经进入线程中
线程1已经进入线程中
线程2完成操作,释放信号量
线程1完成操作,释放信号量
线程1已经进入线程中
线程2已经进入线程中
线程2完成操作,释放信号量
线程1完成操作,释放信号量
线程1已经进入线程中
当前已经有线程进入了临界区,线程2线程等待
线程1完成操作,释放信号量
线程1已经进入线程中
线程1完成操作,释放信号量
线程1已经进入线程中
线程1完成操作,释放信号量
线程1已经进入线程中
线程1完成操作,释放信号量
线程1已经进入线程中
线程1完成操作,释放信号量
线程1已经进入线程中
线程1完成操作,释放信号量
线程1已经进入线程中
线程1完成操作,释放信号量
线程1已经进入线程中
线程1完成操作,释放信号量
线程1已经进入线程中
线程1完成操作,释放信号量
线程1已经进入线程中
线程1完成操作,释放信号量
线程2已经进入线程中
线程2完成操作,释放信号量
线程1已经进入线程中
线程1完成操作,释放信号量
线程2已经进入线程中
线程2完成操作,释放信号量
线程1已经进入线程中
线程1完成操作,释放信号量
线程2已经进入线程中
线程2完成操作,释放信号量
线程1已经进入线程中
线程1完成操作,释放信号量
线程2已经进入线程中
线程2完成操作,释放信号量
线程1已经进入线程中
线程1完成操作,释放信号量
线程2已经进入线程中
线程2完成操作,释放信号量
线程1已经进入线程中
线程1完成操作,释放信号量
线程2已经进入线程中
线程2完成操作,释放信号量
线程1已经进入线程中
线程1完成操作,释放信号量
线程2已经进入线程中
线程2完成操作,释放信号量
线程1已经进入线程中
线程1完成操作,释放信号量
线程2已经进入线程中
线程2完成操作,释放信号量
线程1已经进入线程中
线程1完成操作,释放信号量
线程2已经进入线程中
线程2完成操作,释放信号量
线程1已经进入线程中
线程1完成操作,释放信号量
线程2已经进入线程中
线程2完成操作,释放信号量
线程1已经进入线程中
线程1完成操作,释放信号量
线程2已经进入线程中
线程2完成操作,释放信号量
线程1已经进入线程中
线程1完成操作,释放信号量
线程2已经进入线程中
线程2完成操作,释放信号量
线程1已经进入线程中
线程1完成操作,释放信号量

Process finished with exit code -1

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值