八宿县网站seo优化排名,雄安新区网站建设,西安做网站培训,58同城推广网站怎么做一、信号量的缺点信号量的使用一定要小心#xff0c;如下图中解决生产者-消费者问题的程序#xff1a;如果在producer的执行函数中#xff0c;将empty与mutex的down操作互换#xff0c;如果此时mutex为0#xff0c;将首先对mutex进行down操作#xff0c;进程陷入阻塞如下图中解决生产者-消费者问题的程序如果在producer的执行函数中将empty与mutex的down操作互换如果此时mutex为0将首先对mutex进行down操作进程陷入阻塞而同时当consumer的执行函数执行到down(mutex)的时候由于mutex为0因此consumer线程也将进入阻塞两个进程都将永远进入阻塞状态这被称为“死锁”这说明使用信号量时一定要非常小心一处很小的错误将有可能导致很大的麻烦因为竞争条件、死锁以及其他一些问题都是不可预测和不可再现的行为为了更易于编写正确的程序一种高级同步原语 -- 管程(monitor)诞生了二、管程一个管程是一个由过程、变量及数据结构等组成的一个集合它们组成一个特殊的模块或软件包。管程内部的共享变量管程内部的条件变量管程内部并行执行的进程对局部于管程内部的共享数据设置初始值的语句进程可以在任何需要的时候调用管程中的过程但是他们不能在管程之外声明的过程中直接访问管程内的数据结构但是需要注意的是管程是语言概念而C语言并不支持它任意时刻管程中只能有一个活跃的进程这一特性是的管程能够有效地完成互斥由编译器选择采取与其他过程调用不同的方法来处理对管程的调用典型的处理方法是当一个进程调用管程过程时该过程中的前几条指令将检查在管程中是否有其他的活跃进程如果有调用进程将被挂起知道另一个进程离开管程将其唤醒如果没有则该调用进程可以进入进入管程时的互斥由编译器负责但通常的做法是用一个互斥量或二元信号量因为是有编译器而非程序员来安排互斥所以出错的可能性要小得多在任何一个时刻写管程的人无需关心编译器是如何实现互斥的他只需要知道将所有的临界区转换成管程过程即可绝不会有两个进程同时执行临界区中的代码。三、管程中的条件变量管程提供了一种实现互斥的渐变途径但是我们还需要一种办法使得进程在无法继续运行时被阻塞解决这个问题的方法就是引入条件变量以及相关的两个操作wait和signal当一个管程过程发现他无法继续运行时(如生产者发现缓冲区已满)他会在某个条件变量上(如full)上执行wait操作该操作导致调用进程自身阻塞并将另一个等在管程外的进程调入管程同时一个进程也可以通过对伙伴正在等待的一个条件变量执行signal操作完成唤醒正在睡眠的伙伴进程但是这个时候就有可能会出现两个活跃进程同时处在管程中的情况这个情况有两种方案可以解决运行新唤醒的进程挂起之前的进程执行signal的进程立即退出管程即规定signal只能作为管程过程的最后一条语句让发信者继续运行直到发信者退出管程后才让被唤醒的进程运行很明显第一种方案更加简单所以一般我们采取这一方案注意条件变量与信号量不同他并不是计数器如果向一个条件变量发送信号而这个条件变量上此时并没有等待进程则这个信号就会丢失也就是说wait必须在signal之前执行wait、signal与sleep、wakeup最大的区别是他们不存在严重的竞争条件因为可能存在一种情况即当一个进程正要去sleep而实际还没有sleep的时候另一个进程企图唤醒他从而造成了wakeup信号的丢失而管程中不会存在这样的问题因为在缓冲区满生产者wait前消费者进程根本不可能进入管程四、代码示例如图所示是用管程实现生产者-消费者问题揭发框架的一个类似于pascal的伪代码java支持用户级进程只要将关键词synchronized加入到方法声明中java就保证这个方法一旦被某个进程执行就不允许其他进程执行它因此我们可以通过这一特性实现管程的编程这个例子其实并不难懂由于有synchronized关键字所以无论是producer要进行的insert方法还是consumer要进行的remove方法都只能让一个进程进入因此他们不需要再担心竞争条件java中并没有条件变量反之java提供了两个过程wait和notify与sleep和wakeup等价但他们并不受竞争条件约束而是通过异常机制实现对中断情况的处理