4. Java并发编程-管程

并发编程已经发展很多年,自分时OS以来就已经存在,相关的理论和技术非常多。 这其中的管程是解决并发编程的关键技术。

什么是管程

指的是管理共享变量以及对共享变量的操作过程,让它们支持并发。 在Java领域即管理类的成员变量和方法,让这个类是线程安全的。
管程的英文是:Monitor, 直译是监视器,在OS领域可意译为管程。

管程(monitor) vs 信号量(semophore)

在OS课程中,我们都会学到信号量,知道可用信号量实现互斥锁和同步变量,分别用来解决并发的两大核心问题:互斥和同步(线程间通信,协作)。而管程和信号量其实是等价的,即:可用信号量实现管程,也能用管程实现信号量。但管程更易使用,所以jdk选择了管程。

MESA模型

在管程的发展史上,先后出现过三种不同的管程模型,分别是:Hasen 模型、Hoare 模型和 MESA 模型。现在广泛应用的是 MESA 模型,Java管程以MESA为参考实现。

管程如何解决互斥问题

管程解决互斥问题的思路就是将共享变量及其对共享变量的操作统一封装起来,同一时刻只允许一个线程进入管程。

管程如何解决线程间同步问题

通过在管程中引入条件变量的概念,且每个条件变量都对应一个等待队列,此处的原理跟信号量实现的条件变量类似。 下面示例是一个阻塞队列的代码实现,其中用到了条件变量。


class BlockingQueue {
    final Lock lock = new ReentrantLock();

    // 条件变量:队列不满
    final Condition notFull = lock.newCondition();

    // 条件变量:队列不空
    final Condition notEmpty = lock.newCondition();

    List<Object> internalQueue = new ArrayList<>();

    void enq(Object o) throws InterruptedException {
        lock.lock();

        try {
            // 队列已满
            while (internalQueue.size() >= 5) {
                notFull.await();
            }

            // 入队
            internalQueue.add(o);

            // 只要入队了说明当前队列不空,唤醒出列线程
            notEmpty.signal();

        } finally {
            lock.unlock();
        }
    }


    void deq() throws InterruptedException {
        lock.lock();

        try {
            // 当前队列为空,线程在非空条件变量队列等待
            while (internalQueue.size() == 0) {
                notEmpty.await();
            }

            internalQueue.remove(0);

            // 只要出列了说明当前队列不满,唤醒入列线程
            notFull.signal();

        } finally {
            lock.unlock();
        }
    }
}

注意判断队列满或空的代码段,使用的是while,原因是调用条件变量的signal(),被唤醒的目标线程并非立即执行,且执行时是获取到互斥锁并且从wait后一行开始,所以当它执行时可能条件又不再满足,所以需要再次做判断

总结

Java语言本身对管程的实现做了精简,即只有一个条件变量,且通过synchronized关键字实现不需要显式打开和关闭互斥锁。通过JDK1.5后的并发包可以支持多个条件变量,但需要显式打开和关闭互斥锁。

编程语言中的两大问题互斥和同步都可以通过管程来实现,很多并发工具的底层类也是基于它们实现。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值