目录
一、生产者-消费者模型
生产者-消费者模型是一个常见的多线程编程模型。一个内存队列,多个生产者线程往内存队列中放数据;多个消费者线程从内存队列中取数据。
(1)内存队列本身要加锁,才能实现线程安全。
(2)阻塞。当内存队列满了,生产者放不进去时,会被阻塞; 当内存队列是空的时候,消费者无事可做,会被阻塞。
(3)双向通知。消费者被阻塞之后,生产者放入新数据,要notify()消费者;反之,生产者被阻塞之后,消费者消费了数据,要notify()生产者。
二、为什么必须和synchronized一起使用
在 Java 里面,wait()和 notify()是 Object 的成员函数, 是基础中的基础。为什么 Java 要把wait()和 notify()放在如此 基础的类里面,而不是作为像 Thread 一类的成员函数,或者其他类 的成员函数呢?
开两个线程,线程A调用f1(),线程B调用f2()。答案已经很明显:两个线程之间要通信,对于同一个对象来说,一个线程调用该对象的wait(),另一个线程调用该对象的notify(),该对
象本身就需要同步! 所以,在调用wait()、notify()之前,要先通过synchronized关键字同步给对象,也就是给该对象加锁。
三、为什么wait()的时候必须释放锁
当线程A进入synchronized(obj1)中之后,也就是对obj1上了锁。此时,调用wait()进入阻塞状态,一直不能退出synchronized 代码块;那么,线程B永远无法进入synchronized(obj1)同步块里, 永远没有机会调用notify(),岂不是死锁了?
在wait()的内部,会先释放锁obj 1,然后进入阻塞状态,之后,它被另外一个线程用notify()唤醒, 去重新拿锁! 其次,wait()调用完成后,执行后面的业务逻辑代 码,然后退出synchronized同步块,再次释放锁。
四、wait()与notify()的问题
生产者本来只想通知消费者,但它把其他的生产者也通知了;消费者本来只想通知生产者,但它被其他的消费者通知了。原因就是wait()和notify()所作用的对象和synchronized所作用的对象是同一 个,只能有一个对象,无法区分队列空和列队满两个条件。这正是Condition要解决的问题。