本帖最后由 zhangjinyu1991 于 2013-2-20 12:24 编辑
同步实现synchronized虽然有”同步”的意思,但它实现的首先是互斥机制,讲究的是消除对临界资源访问的竞争,而不关心访问线程之间的步调。而要实现同步:不仅要消除对临界资源访问的竞争,还要关心访问线程之间的步调。
所以,用以下公式来表达同步机制的实现再合适不过了:
Java的同步机制=存取共享资源的互斥机制+线程间的通信机制
存取共享资源的互斥机制我们已经知道了用synchronized来实现了,那线程间的通信怎么实现呢?
线程间的通信线程间的通信通过Object类中的方法:wait()、notify()、notifyAll()来实现。
wait():暂停当前线程的执行,并释放所持有的锁,进入等待状态。
notify():唤醒一个等待线程。
notifyAll():唤醒所有等待的线程。
这三个方法都是Object类的final方法,所以不能被重写。
这三个方法必须要与synchronized一起使用,只能直接或间接地用于临界区中。
注意:我在网上就看到了有位博友写的一篇文章(http://blog.csdn.net/zyplus/article/details/6672775),他说”从语法角度来说就是Obj.wait(),Obj.notify必须在synchronized(Obj){...}语句块内“,这是直接用于临界区,其实也可以:比如说用在临界资源的一个方法put()中,但临界区中有调用这个方法就可以了(我下面的那个生产者-消费者案例就是这样用的)。
下面再来看看一个有关线程同步的经典案例:生产者-消费者问题- /**
- * 生产者与消费者问题
- * 分析
- * 仓库类Warehouse 生产者类Producer 消费者类Consumer
- * 临界资源->仓库类Warehouse 临界区->存取产品的动作(代码)
- * @author jin
- *
- */
- public class ProducerConsumer {
- /**
- * @param args
- */
- public static void main(String[] args) {
- // TODO Auto-generated method stub
- WareHouse buffer=new WareHouse();
- (new Producer(buffer)).start();
- (new Consumer(buffer)).start();
- }
- }
- class WareHouse{
- private int product; // 仓库中的产品
- private boolean isEmpty=true; // 标记仓库是否为空
- public void put(int product_put){ //向仓库放入产品
- // 若仓库不为空,则进入等待状态;
- while(!isEmpty){
- try {
- wait();
- } catch (InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- // 若为空,则向仓库放入产品(放入了产品当能就要标记仓库不为空咯)并发出通知
- this.product=product_put;
- this.isEmpty=false;
- notify();
- }
- public int get(){ //从仓库取出产品
- // 若仓库为空,取产品这个动作的线程自然要进入等待状态了
- while(isEmpty){
- try {
- wait();
- } catch (InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- // 若仓库不为空,返回产品(取出了产品仓库就空了,就要标记仓库为空)并发出通知
- isEmpty=true;
- notify();
- return this.product;
- }
- }
- class Producer extends Thread{
- private WareHouse buffer; // 将要访问的临界资源
- public Producer(WareHouse buffer) {
- // TODO Auto-generated constructor stub
- this.buffer=buffer;
- }
-
- @Override
- public void run() {
- // TODO Auto-generated method stub
- synchronized (buffer) {
- for(int i=1; i<=5; i++){ // 假设生产5个产品:1、2、3、4、5
- buffer.put(i);
- System.out.println("存入产品:"+i);
- }
- }
- }
- }
- class Consumer extends Thread{
- private WareHouse buffer; // 将要访问的临界资源
- public Consumer(WareHouse buffer) {
- // TODO Auto-generated constructor stub
- this.buffer=buffer;
- }
-
- @Override
- public void run() {
- // TODO Auto-generated method stub
- synchronized (buffer) {
- for(int i=1; i<=5; i++){ // 生产了5个产品,我们也就5次去拿产品
- System.out.println("取出产品:"+buffer.get());
- }
- }
- }
- }
复制代码 |