Java wait和notify 我知道你在疑惑什么

来源:互联网 发布:淘宝网评价怎么删除 编辑:程序博客网 时间:2024/04/28 20:04
    你要知道什么叫“锁”!
    任何一个对象实例都可以作为锁,也就是说,一个实例,在同一时间只能被一个线程占有。

    看下面的小程序:


------------
    t1和t2同时运行。它们都将运行类A中的run()方法,synchronized(s) 是一个以实例s为锁的同步块。

    假若t1线程先运行到synchronzied这一句代码,t1发现s没有被占有,那么t1将其占有并执行里面的代码。

    这时候t2也运行到了synchronized这一句代码,t2发现s已经被占有,则t2进入阻塞状态,t2一直在监视着s,t2一直在等,等t1运行完了,s被释放。这时t2立刻抢占s,并开始运行里面的代码。

    由于每一个实例都有这种只能被一个线程占有的特性,书面语言把这叫做“锁”,所以你可以随便创建一个类的实例,将其专门作为锁来使用。
------------

【wait()和notify()】以上面的代码为基础修改了一下:


------------
    现在加入了wait()和notify()方法。

    注意:调用的是s的wait和notify。并不是说把s暂停,把s唤醒。

    wait只能让当前正在运行这句代码的线程暂停。

    上面代码的流程是:

    第1次,t1运行到了s.notify(),但此时在s对象上,没有线程处于wait状态,所以第1次运行s.notify()没什么效果。
    紧接着,t1运行到了s.wait(),于是t1放开了s,s被释放,并且t1线程停了,变为阻塞状态,
   (但t1仍然在做一件事,就是等,t1一直在监视s,如果在其他什么地方运行了s.notify(),那么就会唤醒在s上等待的一个线程。)

    与此同时,t2也在运行,这时t2运行到了run方法,占有了s,接着t2运行了s.notify().这时我们知道在s上有一个等待着的线程,就是t1.
此时,t1被唤醒,t1开始抢占s,但s此刻是被t2占有的。接着t2运行到了s.wait(),于是t2解开了s的锁,并且t2暂停了(但t2一直在等...)

    这样就形成了两个线程交替运行。
------------

    相信你已经理解把对象作为锁来用的方法了。
    对于同步方法:同步方法默认以this作为锁,且不可更改。所以大多数时候我们都用同步代码块。