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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/555565.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在IDEA中解决jar包冲突的神操作-必看

在开发过程中,经常会遇到导入jar包后jar包冲突的情况,大家也都知道,解决jar包冲突通常都比较麻烦,要找到多余的依赖,把低版本的依赖去掉。而大家通常能搜到IDEA解决jar包冲突的方法,应该是这样的&#xff1…

java 图片不能正常移动_Java,我的图像不会更新/移动

我对Java的东西是一个新手,但是..在网上阅读了很多内容之后,我一直在努力开发这款游戏并开始使用,我正在使用一些图片。我想通过KeyListener来更新他们的立场以展示运动的过程,我相信。不幸的是,图像仍然在同一个地方&…

MySQL保存或更新 saveOrUpdate

1. 引子 在项目开发过程中&#xff0c;有一些数据在写入时候&#xff0c;若已经存在&#xff0c;则覆盖即可。这样可以防止多次重复写入唯一键冲突报错。下面先给出两个MyBatis配置文件中使用saveOrUpdate的示例 <!-- 单条数据保存 --> <insert id"saveOrUpdat…

Java调用动态库 缺点_java调用动态库(dll)的一些问题

javac1)dos切换到java文件所在目录&#xff0c;使用javac编译出class文件javah的一些问题&#xff1a;1)切换到src目录下2)设置路径命令&#xff1a;set classpathsrc目录的完全路径3)执行 javah 类名(带包的名称)&#xff0c;将生成的文件改名为“testdll.h”4.DLL的创建 :1)创…

分布式事务六种解决方案

前言 事务想必大家并不陌生&#xff0c;至于什么是 ACID&#xff0c;也是老生常谈了。不过为了保证文章的完整性确保所有人都听得懂&#xff0c;我还是得先说说 ACID&#xff0c;然后再来介绍下什么是分布式事务和常见的分布式事务包括 2PC、3PC、TCC、本地消息表、消息事务、…

java判断对象无数据_java 对象属性不能为空判断

如何判断一个对象里的属性是否都为空的怎么判断一个对象里的属性是否都为空的怎么判断一个对象里的属性是否都为空的&#xff0c;或者判断该对象是否是一个实体&#xff01;引用:怎么判断一个对象里的属性是否都为空的&#xff0c;或者判断该对象是否是一个实体&#xff01;我明…

Minor GC、Major GC和Full GC之间的区别

概念&#xff1a; ● 新生代 GC&#xff08;Minor GC&#xff09;&#xff1a;从年轻代空间&#xff08;包括 Eden 和 Survivor 区域&#xff09;回收内存被称为 Minor GC,因为 Java 对象大多都具备朝生夕灭的特性&#xff0c;所以 Minor GC 非常频繁&#xff0c;一般回收速度也…

SpringBoot——实现WebService接口服务端以及客户端开发

文章目录一、服务端代码开发1、pom依赖2、接口类3、接口实现类4、webservice配置文件2、客户端开发&#xff08;1&#xff09;pom依赖&#xff08;2&#xff09;封装客户端方法clientUtil&#xff08;3&#xff09;调用接口类&#xff08;4&#xff09;运行结果我们经常需要在两…

java 磁盘空间_如何使用Java查找剩余的磁盘空间?

Java 1.7的API稍有不同&#xff0c;可用getTotalSpace()&#xff0c;getUnallocatedSpace()和getUsableSpace()方法通过FileStore类查询可用空间。NumberFormat nf NumberFormat.getNumberInstance();for (Path root : FileSystems.getDefault().getRootDirectories()) {Syste…

springboot集成webService开发详解

webService优缺点 webService优点 WebService是一种跨编程语言和跨操作系统平台的远程调用技术远程调用技术&#xff1a;不用担心防火墙的问题 webService缺点 服务端接口方为webservice则客户端也必须使用webservice&#xff0c;双方保持一致因为webservice使用xml传输数据…

WebService就是这么简单

WebService介绍 首先我们来谈一下为什么需要学习webService这样的一个技术吧…. 问题一 如果我们的网站需要提供一个天气预报这样一个需求的话&#xff0c;那我们该怎么做&#xff1f;&#xff1f;&#xff1f;&#xff1f;&#xff1f; 天气预报这么一个功能并不是简单的J…

python使用xlrd读取xlsx文件_$ 用python处理Excel文档(1)——用xlrd模块读取xls/xlsx文档...

本文主要介绍xlrd模块读取Excel文档的基本用法&#xff0c;并以一个GDP数据的文档为例来进行操作。1. 准备工作&#xff1a;1. 安装xlrd&#xff1a;pip install xlrd2. 准备数据集&#xff1a;从网上找到的1952~2012年中国国内GDP的数据&#xff0c;数据结构如下&#xff1a;2…

WebService技术详解CXF

WebService WebService简介 Web Service技术&#xff0c; 能使得运行在不同机器上的不同应用无须借助附加的、专门的第三方软件或硬件&#xff0c; 就可相互交换数据或集成。依据Web Service规范实施的应用之间&#xff0c; 无论它们所使用的语言、 平台或内部协议是什么&…

java 类 加载 初始化_java中类的初始化和加载

最近在阅读孙卫琴的java面向对象一书中&#xff0c;看到对java中类的初始化和加载中的论述比较系统&#xff0c;故笔记之1)类的初始化&#xff0c;JAVA在初始化一个类时&#xff0c;以下步骤A 假如类存在直接的父类&#xff0c;并且这个父类还没有初始化&#xff0c;则先初始化…

Java webservice详解

文章目录1 webservice概述2 webservice核心要素2.1 SOAP2.2 WSDL3 webservice的使用场景4 webservice的结构5 Java中的webservice5.1 webservice服务端5.2 webservice客户端6 WDSL文件说明7 webservice 请求与响应监控8 webservice 在Tomcat中发布9 在Spring中使用webservice1 …

java net php_Java.netPHP比较 | php外包与php技术服务商

Java\.net\PHP比较首先&#xff0c;我们把Java 、.Net、 PHP应用方面占有率做个比较&#xff0c;简单的把目前主流应用分成两个大类&#xff0c;一个是企业应用&#xff0c;一个是Web网站应用&#xff0c;下面这个表格是我归纳的&#xff0c;不一定准确&#xff0c;但是能说明一…

HashMap、HashTable、ConcurrentHashMap、HashSet区别 线程安全类

HashMap专题&#xff1a;HashMap的实现原理–链表散列 HashTable专题&#xff1a;Hashtable数据存储结构-遍历规则&#xff0c;Hash类型的复杂度为啥都是O(1)-源码分析 Hash,Tree数据结构时间复杂度分析&#xff1a;HashMap, HashTable&#xff0c;HashSet,TreeMap 的时间复杂…

hibernate mysql cascade_Hibernate第五篇【inverse、cascade属性详解】

前言上一篇博文已经讲解了一对多和多对一之间的关系了&#xff0c;一对多和多对一存在着关联关系(外键与主键的关系)。本博文主要讲解Inverse属性、cascade属性。这两个属性对关联关系都有影响Inverse属性Inverse属性&#xff1a;表示控制权是否转移..true:控制权已转移【当前一…

java请编写公共类继承抽象类_(Java相关)怎么理解抽象类,继承和接口?

著作权归作者所有。商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处。作者&#xff1a;海子来源&#xff1a;博客园一.抽象类在了解抽象类之前&#xff0c;先来了解一下抽象方法。抽象方法是一种特殊的方法&#xff1a;它只有声明&#xff0c;而没有具体的实现。抽…

Maven:repositories、distributionManagement、pluginRepositories中repository的区别

一、repositories中的repository二、distributionManagement中的repository三、pluginRepositories中的repository 一、repositories中的repository 表示从什么库地址可以下载项目依赖的库文件&#xff0c;比如&#xff1a; <repositories><repository><id>…