java锁之wait,notify(wait会释放锁,notify仅仅只是通知,不释放锁)(转)
来源:互联网 发布:图的广度优先遍历c语言 编辑:程序博客网 时间:2024/06/16 00:43
wait是指在一个已经进入了同步锁的线程内,让自己暂时让出同步锁,以便其他正在等待此锁的线程可以得到同步锁并运行, 只有其他线程调用了notify方法(notify并不释放锁,只是告诉调用过wait方法的线程可以去参与获得锁的竞争了,但不是马上得到锁,因为锁还 在别人手里,别人还没释放。如果notify/notifyAll方法后面的代码还有很多,需要这些代码执行完后才会释放锁),调用wait方法的一个或多个线程就会解除wait状态,重新参与竞争对象锁,程序如果可以再次得到锁,就可以继续向下运行。
1)wait()、notify()和notifyAll()方法是本地方法,并且为final方法,无法被重写。
2)当前线程必须拥有此对象的monitor(即锁),才能调用某个对象的wait()方法能让当前线程阻塞,
(这种阻塞是通过提前释放synchronized锁,重新去请求锁导致的阻塞,这种请求必须有其他线程通过notify()或者notifyAll()唤醒重新竞争获得锁)
3)调用某个对象的notify()方法能够唤醒一个正在等待这个对象的monitor的线程,如果有多个线程都在等待这个对象的monitor,则只能唤醒其中一个线程;
(notify()或者notifyAll()方法并不是真正释放锁,必须等到synchronized方法或者语法块执行完才真正释放锁)
4)调用notifyAll()方法能够唤醒所有正在等待这个对象的monitor的线程,唤醒的线程获得锁的概率是随机的,取决于cpu调度
例子1(错误使用导致线程阻塞):三个线程,线程3先拥有sum对象的锁,然后通过sum.notify()方法通知等待sum锁的线程去获得锁,但是这个时候线程1,2并没有处于wait()导致的阻塞状态,而是在synchronized方法块处阻塞了,所以,这次notify()根本没有通知到线程1,2。然后线程3正常结束,释放掉sum锁,这个时候,线程1就立刻获得了sum对象的锁(通过synchronized获得),然后调用sum.wait()方法释放掉sum的锁,线程2随后获得了sum对象的线程锁(通过synchronized获得),这个时候线程1,2都处于阻塞状态,但是悲催的是,这之后再也没有线程主动调用sum.notify()或者notifyAll()方法显示唤醒这两个线程,所以程序阻塞
- public class CyclicBarrierTest {
- public static void main(String[] args) throws Exception {
- final Sum sum=new Sum();
- new Thread(new Runnable() {
- @Override
- public void run() {
- try {
- synchronized (sum) {
- System.out.println(”thread3 get lock”);
- sum.sum();
- sum.notifyAll(); //此时唤醒没有作用,没有线程等待
- Thread.sleep(2000);
- System.out.println(”thread3 really release lock”);
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }).start();
- new Thread(new Runnable() {
- @Override
- public void run() {
- try {
- synchronized (sum) {
- System.out.println(”thread1 get lock”);
- sum.wait();//主动释放掉sum对象锁
- System.out.println(sum.total);
- System.out.println(”thread1 release lock”);
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }).start();
- new Thread(new Runnable() {
- @Override
- public void run() {
- try {
- synchronized (sum) {
- System.out.println(”thread2 get lock”);
- sum.wait(); //释放sum的对象锁,等待其他对象唤醒(其他对象释放sum锁)
- System.out.println(sum.total);
- System.out.println(”thread2 release lock”);
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }).start();
- }
- }
- class Sum{
- public Integer total=0;
- public void sum() throws Exception{
- total=100;
- Thread.sleep(5000);
- }
- }
public class CyclicBarrierTest { public static void main(String[] args) throws Exception { final Sum sum=new Sum(); new Thread(new Runnable() { @Override public void run() { try { synchronized (sum) { System.out.println("thread3 get lock"); sum.sum(); sum.notifyAll(); //此时唤醒没有作用,没有线程等待 Thread.sleep(2000); System.out.println("thread3 really release lock"); } } catch (Exception e) { e.printStackTrace(); } } }).start(); new Thread(new Runnable() { @Override public void run() { try { synchronized (sum) { System.out.println("thread1 get lock"); sum.wait();//主动释放掉sum对象锁 System.out.println(sum.total); System.out.println("thread1 release lock"); } } catch (Exception e) { e.printStackTrace(); } } }).start(); new Thread(new Runnable() { @Override public void run() { try { synchronized (sum) { System.out.println("thread2 get lock"); sum.wait(); //释放sum的对象锁,等待其他对象唤醒(其他对象释放sum锁) System.out.println(sum.total); System.out.println("thread2 release lock"); } } catch (Exception e) { e.printStackTrace(); } } }).start(); }}class Sum{ public Integer total=0; public void sum() throws Exception{ total=100; Thread.sleep(5000); }}
运行结果:
- thread3 get lock
- thread3 really release lock
- thread2 get lock
- thread1 get lock
- //程序后面一直阻塞
thread3 get lockthread3 really release lockthread2 get lockthread1 get lock//程序后面一直阻塞例子2:还是上面程序,顺序不同,把线程3放到最下面。最后线程1,2都因为没有再次获得线程导致线程阻塞
运行过程:
线程1先运行获得sum对象锁(通过synchronized),但是随后执行了sum.wait()方法,主动释放掉了sum对象锁,然后线程2获得了sum对象锁(通过synchronized),也通过sum.wait()失去sum的对象锁,最后线程3获得了sum对象锁(通过synchronized),主动通过sum.notify()通知了线程1或者2,假设是1,线程1重新通过notify()/notifyAll()的方式获得了锁,然后执行完毕,随后线程释放锁,然后这个时候线程2成功获得锁,执行完毕。
- public class CyclicBarrierTest {
- public static void main(String[] args) throws Exception {
- final Sum sum=new Sum();
- new Thread(new Runnable() {
- @Override
- public void run() {
- try {
- synchronized (sum) {
- System.out.println(”thread1 get lock”);
- sum.wait();//主动释放sum对象锁,等待唤醒
- System.out.println(sum.total);
- System.out.println(”thread1 release lock”);
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }).start();
- new Thread(new Runnable() {
- @Override
- public void run() {
- try {
- synchronized (sum) {
- System.out.println(”thread2 get lock”);
- sum.wait(); //主动释放sum对象锁,等待唤醒
- System.out.println(sum.total);
- System.out.println(”thread2 release lock”);
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }).start();
- new Thread(new Runnable() {
- @Override
- public void run() {
- try {
- synchronized (sum) {
- System.out.println(”thread3 get lock”);
- sum.sum();
- sum.notifyAll();//唤醒其他等待线程(线程1,2)
- Thread.sleep(2000);
- System.out.println(”thread3 really release lock”);
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }).start();
- }
- }
- class Sum{
- public Integer total=0;
- public void sum() throws Exception{
- total=100;
- Thread.sleep(5000);
- }
- }
public class CyclicBarrierTest { public static void main(String[] args) throws Exception { final Sum sum=new Sum(); new Thread(new Runnable() { @Override public void run() { try { synchronized (sum) { System.out.println("thread1 get lock"); sum.wait();//主动释放sum对象锁,等待唤醒 System.out.println(sum.total); System.out.println("thread1 release lock"); } } catch (Exception e) { e.printStackTrace(); } } }).start(); new Thread(new Runnable() { @Override public void run() { try { synchronized (sum) { System.out.println("thread2 get lock"); sum.wait(); //主动释放sum对象锁,等待唤醒 System.out.println(sum.total); System.out.println("thread2 release lock"); } } catch (Exception e) { e.printStackTrace(); } } }).start(); new Thread(new Runnable() { @Override public void run() { try { synchronized (sum) { System.out.println("thread3 get lock"); sum.sum(); sum.notifyAll();//唤醒其他等待线程(线程1,2) Thread.sleep(2000); System.out.println("thread3 really release lock"); } } catch (Exception e) { e.printStackTrace(); } } }).start(); }}class Sum{ public Integer total=0; public void sum() throws Exception{ total=100; Thread.sleep(5000); }}
执行结果:
- thread1 get lock
- thread2 get lock
- thread3 get lock
- thread3 really release lock
- 100
- thread2 release lock
- 100
- thread1 release lock
thread1 get lockthread2 get lockthread3 get lockthread3 really release lock100thread2 release lock100thread1 release lock
- java锁之wait,notify(wait会释放锁,notify仅仅只是通知,不释放锁)
- java锁之wait,notify(wait会释放锁,notify仅仅只是通知,不释放锁)
- java锁之wait,notify(wait会释放锁,notify仅仅只是通知,不释放锁)(转)
- java wait()notify释放锁
- 阻塞队列(CountDownLatch代替notify+wait解决wait释放锁,notify不释放锁问题)
- java多线程什么时候释放锁—wait()、notify()
- java多线程什么时候释放锁—wait()、notify()
- wait ,notfiy 配合synchronized关键字使用,wait立即释放锁,而notify并不立即释放
- wait(),notify()和锁
- wait,notify,synchronized锁
- wait notify 锁机制
- 正确理解线程等待和释放(wait/notify)
- 理解线程的等待释放(wait/notify)
- 正确理解线程等待和释放(wait/notify)
- java 中的 wait/notify 同步锁机制
- JAVA之wait¬ify&Condition
- JAVA多线程之wait/notify
- JAVA多线程之wait/notify
- C/C++ 语言中的表达式求值
- 使用es6 proxy 自动监听对象
- 第六章 递归,内联,重载,作用域和存储类型
- 心理咨询预约如何在微信公众号如何快速实现
- freertos内核走读2——task任务调度机制(一)
- java锁之wait,notify(wait会释放锁,notify仅仅只是通知,不释放锁)(转)
- 每周阅读清单:Android 架构,小工具,Google 能访问了?
- Android异步通信——HandlerThread源码解析
- HDU 2159 FATE
- 上传本地项目到github
- 为什么非全站升级HTTPS不可?
- java语言基础(25)——面向对象(new对象的时候内存中发生了哪些变化)
- 20170323
- C++模拟DNS分布式查询