关于生产者消费者问题的理解

1.理论思考

a.生产者消费者问题既包含了进程之间的互斥关系(一组消费者和一组生产者对于缓冲区的操作都是互斥的),也包含了进程间的同步关系(消费者和生产者之间的通信),注意empty的判别要写在mutex之前

b.与Java语言中的生产者消费者的对比,Java语言中的synconized锁肯定是来源于操作系统管程的思想,这是毋庸置疑的,而在生消问题实现的过程中,Java使用锁对象的方式将对象交给synconized锁去托管互斥关系,利用wait和notify方法来实现进程直接制约关系,所谓的线程通信。

c.生产者利用wait方法使得当缓冲区满的时候进入永久休眠区,并释放锁的占用以及cpu资源,所以在这里不需要考虑是不是会导致因为wait(empty)导致死锁,因为这里的mutex互斥锁变成了synconized锁托管的对象,当wait()执行的时候进程进入永久休眠区,同时放弃了锁的占用,从而在下一个周期生产者被唤醒,消费者的直接制约实现同理。

d.在信号量实现生消问题的时候,如果把wait(mutex) 和 wait(empty)替换,会导致死锁的原因是,消费者先使用wait(mutex)然后empty等于0的情况下,消费者阻塞,它是放弃了处理机,但是它不像管程同时放弃了锁,导致消费者还被锁着。

ps

Object.wait()方法,会释放锁资源以及CPU资源。

Thread.sleep()方法,不会释放锁资源,但是会释放CPU资源。

首先,wait()方法是让一个线程进入到阻塞状态,而这个方法必须要写在一个Synchronized同步代码块里面。

因为wait/notify是基于共享内存来实现线程通信的工具,这个通信涉及到条件的竞争,所以在调用这两个方法之前必须要竞争锁资源。

当线程调用wait方法的时候,表示当前线程的工作处理完了,意味着让其他竞争同一个共享资源的线程有机会去执行。

但前提是其他线程需要竞争到锁资源,所以wait方法必须要释放锁,否则就会导致死锁的问题。

然后,Thread.sleep()方法,只是让一个线程单纯进入睡眠状态,这个方法并没有强制要求加synchronized同步锁。

而且从它的功能和语义来说,也没有这个必要。

当然,如果是在一个Synchronized同步代码块里面调用这个Thread.sleep,也并不会触发锁的释放。

最后,凡是让线程进入阻塞状态的方法,操作系统都会重新调度实现CPU时间片切换,这样设计的目的是提升CPU的利用率。