我所理解的管程以及Java中的管程样例
发布网友
发布时间:1天前
我来回答
共1个回答
热心网友
时间:2024-12-04 19:31
从PV操作说起,我们需要解决的问题是确保只有一个进程能访问临界资源,因此引入了中间层的概念。这个层需要满足条件:判定和操作要原子性。通常有两种实现方法:主动轮询和接受唤醒。主动轮询会一直占用资源,而接受唤醒则可能导致大量上下文切换,但结合自旋和阻塞方式可以平衡性能。
信号量机制不仅实现互斥,还能同步进程。它是原语实现,保证了操作的原子性。整数型信号量通过主动轮询实现互斥,但可能导致忙等。引入记录型信号量,通过队列避免忙等,让进程能加入阻塞队列等待资源。
信号量的值表示可用资源数量,如图所示,初始值为5意味着5个进程可以同时访问资源。当资源被占用,后续进程被阻塞直到资源可用。
从信号量到管程,我们认识到信号量有局限性,如无法区分不同条件的唤醒需求。管程管理共享变量和操作,支持并发。管程本质上管理中间人,封装了信号量和队列操作。共享变量包括信号量(值和队列)。唤醒分为从未进入管程和已进入并自我阻塞的进程。
管程实现互斥时,使用价值为1的信号量。两个进程需要访问临界区时,先进入的进程先P操作,发现资源可用后进入,而后来的进程则被阻塞。同步则涉及进程结束后的唤醒,可以全部或有条件。EntryQueue和WaitQueue区分从未进入管程和自我阻塞的进程。
条件变量实质上是一个队列,执行wait()将进程加入队列并阻塞,signal()唤醒队列中的一个进程。Java的synchronized简化了MESA模型,仅支持一个条件变量,但并发包实现支持多个条件变量,需要手动管理锁。
生产者消费者模式观察管程运行流程,发现同步方法中调用wait()和notify()至关重要。调用wait()释放锁,必须先获得锁。在synchronized代码块中调用,确保了资源的正确管理。ReentrantLock实现则允许更精确的唤醒,减少竞争。