wait是指在一个已经进入了同步锁的线程内,让自己暂时让出同步锁,以便其他正在等待此锁的线程可以得到同步锁并运行,只有其他线程调用了notify方法(notify并不释放锁,只是告诉调用过wait方法的线程可以去参与获得锁的竞争了,但不是马上得到锁,因为锁还在别人手里,别人还没释放),调用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);

}

}

thread3 get lock

thread3 really release lock

thread2 get lock

thread1 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);

}

}

thread1 get lock

thread2 get lock

thread3 get lock

thread3 really release lock

100

thread2 release lock

100

thread1 release lock

java wait 释放锁_JAVA锁之wait,notify(wait会释放锁,notify仅仅只是通知,不释放锁)...相关推荐

  1. java中什么是释放已经持有的锁_java多线程什么时候释放锁

    由于等待一个锁定线程只有在获得这把锁之后,才能恢复运行,所以让持有锁的线程在不需要锁的时候及时释放锁是很重要的.在以下情况下,持有锁的线程会释放锁: 1.当前线程的同步方法.代码块执行结束的时候释放 ...

  2. java投票锁_Java并发编程锁之独占公平锁与非公平锁比较

    Java并发编程锁之独占公平锁与非公平锁比较 公平锁和非公平锁理解: 在上一篇文章中,我们知道了非公平锁.其实Java中还存在着公平锁呢.公平二字怎么理解呢?和我们现实理解是一样的.大家去排队本着先来 ...

  3. java 共享锁 独占锁_Java并发编程锁之独占公平锁与非公平锁比较

    Java并发编程锁之独占公平锁与非公平锁比较 公平锁和非公平锁理解: 在上一篇文章中,我们知道了非公平锁.其实Java中还存在着公平锁呢.公平二字怎么理解呢?和我们现实理解是一样的.大家取排队本着先来 ...

  4. java 锁_Java 锁之我见

    今天我们来聊聊 Java 里面的各种锁:偏向锁.轻量级锁.重量级锁,以及三个锁之间是如何进行锁膨胀的. 众所周知,线程阻塞带来的上下文切换的代价是很大的,Java 为了尽量减少上下文的切换从而引入了更 ...

  5. java mysql 分布式锁_Java分布式锁之数据库方式实现

    之前的文章<Java分布式锁实现>中列举了分布式锁的3种实现方式,分别是基于数据库实现,基于缓存实现和基于zookeeper实现.三种实现方式各有可取之处,本篇文章就详细讲解一下Java分 ...

  6. java让线程空转_Java锁:悲观/乐观/阻塞/自旋/公平锁/闭锁,锁消除CAS及synchronized的三种锁级别...

    JAVA LOCK 大全 [TOC] 一.广义分类:乐观锁/悲观锁 1.1 乐观锁的实现CAS (Compare and Swap) 乐观锁适合低并发的情况,在高并发的情况下由于自旋,性能甚至可能悲观 ...

  7. java B锁_Java中15种锁的介绍

    原标题:Java中15种锁的介绍 在读很多并发文章中,会提及各种各样锁如公平锁,乐观锁等等,这篇文章介绍各种锁的分类.介绍的内容如下: 1.公平锁 / 非公平锁 2.可重入锁 / 不可重入锁 3.独享 ...

  8. java多线程安全解决方案_java常用知识:多线程安全问题的解决方法-Lock锁

    jdk1.5后出现的 两个方法: void Lock() void unlock() 使用步骤: 1.在成员位置创建一个ReentrantLock对象 2.在可能出现安全问题的代码前调用Lock接口中 ...

  9. java线程池 锁_java多线程——锁

    这是多线程系列第四篇,其他请关注以下: 如果你看过前面几篇关于线程的文字,会对线程的实现原理了然于胸,有了理论的支持会对实践有更好的指导,那么本篇会偏重于线程的实践,对线程的几种应用做个简要的介绍. ...

最新文章

  1. Open3d学习计划—高级篇 7(颜色映射)
  2. Android Launcher3(一) -- 启动过程
  3. 【Kali渗透全方位实战】使用Nmap进行端口探测-发现脆弱站点
  4. 使用Xpose突破安卓App禁止截屏限制
  5. 找不到类型{0} 它在 ServiceHost 指令中提供为 Service 特性值
  6. 函数sigqueue
  7. dotnet若干说明图片
  8. 从零到破万节点!支撑618大促背后的蚂蚁金服Kubernetes集群
  9. 开机后网络连接迟迟没有反映是怎么回事?
  10. 阿尔伯塔大学 计算机科学,阿尔伯塔大学计算机科学专业入学要求及申请费用盘点...
  11. 知识图谱在应用过程中,主要面临哪些困难?
  12. 未来的世界是,方向比努力重要,能力比知识重要,健康比成绩重要,生活比文凭重要,情商比智商重要!
  13. 父组件给孙子组件传值
  14. Adobe Acrobat 虚拟打印机安装方法
  15. 2 Java并发原理精讲课程学习笔记
  16. 操作系统批处理阶段--单道和多道批处理系统处理优点缺点以及过程,分时实时操作系统
  17. 云计算课程大纲,Linux云计算运维课程视频
  18. IND-CPA、IND-CCA1和IND-CCA2详解
  19. 场内交易基金实时数据 API 数据接口
  20. 数学建模多元线性回归内生性问题的蒙特卡洛模拟matlab代码

热门文章

  1. 本地 服务器 文件传输,本地服务器文件传输
  2. mc有什么红石机器人_我的世界10月考试!来测测你的MC成绩吧~
  3. android 颜色范围,Android系统颜色的适用范围
  4. 并行计算机架构_计算机科学组织| 并行处理
  5. Java LineNumberReader getLineNumber()方法及示例
  6. 实战,实现幂等的8种方案!
  7. 面试官 | 讲一下如何给高并发系统做限流?
  8. Redis使用不当导致应用卡死
  9. 一个4体低位交叉的存储器_前交叉韧带术后关节粘连的康复策略
  10. Mybatis逆向工程自动生成代码文件