转:JAVA 的wait(), notify()与synchronized同步机制
原文地址:http://blog.csdn.net/zyplus/article/details/6672775
转自:https://www.cnblogs.com/x_wukong/p/4009709.html
主要这句话 :Obj.wait(),与Obj.notify()必须要与synchronized(Obj)一起使用
在JAVA中,是没有类似于PV操作、进程互斥等相关的方法的。JAVA的进程同步是通过synchronized()来实现的,需要说明的是,JAVA的synchronized()方法类似于操作系统概念中的互斥内存块,在JAVA中的Object类型中,都是带有一个内存锁的,在有线程获取该内存锁后,其它线程无法访问该内存,从而实现JAVA中简单的同步、互斥操作。明白这个原理,就能理解为什么synchronized(this)与synchronized(static XXX)的区别了,synchronized就是针对内存区块申请内存锁,this关键字代表类的一个对象,所以其内存锁是针对相同对象的互斥操作,而static成员属于类专有,其内存空间为该类所有成员共有,这就导致synchronized()对static成员加锁,相当于对类加锁,也就是在该类的所有成员间实现互斥,在同一时间只有一个线程可访问该类的实例。如果只是简单的想要实现在JAVA中的线程互斥,明白这些基本就已经够了。但如果需要在线程间相互唤醒的话就需要借助Object.wait(), Object.nofity()了。
Obj.wait(),与Obj.notify()必须要与synchronized(Obj)一起使用,也就是wait,与notify是针对已经获取了Obj锁进行操作,从语法角度来说就是Obj.wait(),Obj.notify必须在synchronized(Obj){...}语句块内。从功能上来说wait就是说线程在获取对象锁后,主动释放对象锁,同时本线程休眠。直到有其它线程调用对象的notify()唤醒该线程,才能继续获取对象锁,并继续执行。相应的notify()就是对对象锁的唤醒操作。但有一点需要注意的是notify()调用后,并不是马上就释放对象锁的,而是在相应的synchronized(){}语句块执行结束,自动释放锁后,JVM会在wait()对象锁的线程中随机选取一线程,赋予其对象锁,唤醒线程,继续执行。这样就提供了在线程间同步、唤醒的操作。Thread.sleep()与Object.wait()二者都可以暂停当前线程,释放CPU控制权,主要的区别在于Object.wait()在释放CPU同时,释放了对象锁的控制。
详细内容参考原文
另外参考:https://blog.csdn.net/xh16319/article/details/8032587
wait()和notify(),notifyAll()是Object类的方法,sleep(),yield(),join()是Thread类的方法。
1、sleep()
使当前线程(即调用该方法的线程)暂停执行一段时间,让其他线程有机会继续执行,但它并不释放对象锁。
也就是说如果有synchronized同步快,其他线程仍然不能访问共享数据。注意该方法要捕捉异常。
// 下面这三行应该是原博说错了 错误根源追溯到 https://zhidao.baidu.com/question/51787355.html ,哪位同学还有精力可以继续追溯下去 = =!
例如有两个线程同时执行(没有synchronized)一个线程优先级为MAX_PRIORITY,另一个为MIN_PRIORITY,如果没有Sleep()方法,
只有高优先级的线程执行完毕后,低优先级的线程才能够执行;但是高优先级的线程sleep(500)后,低优先级就有机会执行了。
总之,sleep()可以使低优先级的线程得到执行的机会,当然也可以让同优先级、高优先级的线程有执行的机会。
//
2、join()
join()方法使调用该方法的线程在此之前执行完毕,也就是等待该方法的线程执行完毕后再往下继续执行。注意该方法也需
要捕捉异常。
3、yield()
该方法与sleep()类似,只是不能由用户指定暂停多长时间,并且yield()方法只能让同优先级的线程有执行的机会。
4、wait()和notify()、notifyAll()
这三个方法用于协调多个线程对共享数据的存取,所以必须在synchronized语句块内使用。
synchronized关键字用于保护共享数据,阻止其他线程对共享数据的存取,但是这样程序的流程就
很不灵活了,如何才能在当前线程还没退出
synchronized数据块时让其他线程也有机会访问共享数据呢?此时就用这三个方法来灵活控制。
wait()方法使当前线程暂停执行并释放对象锁标示,让其他线程可以进入synchronized数据块,当前线程被放入对象
等待池中。当调用notify()方法后,将从对象的等待池中移走一个任意的线程并放到锁标志等待池中,只有锁标志
等待池中线程能够获取锁标志;如果锁标志等待池中没有线程,则notify()不起作用。
notifyAll()则从对象等待池中移走所有等待那个对象的线程并放到锁标志等待池中。
注意 这三个方法都是java.lang.Object的方法。
yeild() 和 sleep()
sleep() 方法使当前运行中的线程睡眠一段时间,进入不可以运行状态,这段时间的长短是由程序设定的,yield方法使当
前线程让出CPU占有权,但让出的时间是不可设定的。
yield()也不会释放锁标志。
实际上,yield()方法对应了如下操作;先检测当前是否有相同优先级的线程处于同可运行状态,如有,则把CPU的
占有权交给次线程,否则继续运行原来的线程,所以yield()方法称为“退让”,它把运行机会让给了同等级的其他线程。
sleep() 方法允许较低优先级的线程获得运行机会,但yield()方法执行时,当前线程仍处在可运行状态,
// 下面关于优先级的那部分应该是原博说错了
所以不可能让出较低优先级的线程此时获取CPU占有权。在一个运行系统中,如果较高优先级的线程没有调用sleep方法,也没有
受到I/O阻塞,那么较低优先级线程只能等待所有较高优先级的线程运行结束,方可有机会运行。
yield()只是使当前线程重新回到可执行状态,所有执行yield()的线程有可能在进入到可执行状态后马上
又被执行,所以yield()方法只能使同优先级的线程有执行的机会。
转:JAVA 的wait(), notify()与synchronized同步机制的更多相关文章
- JAVA 的wait(), notify()与synchronized同步机制
转自:http://blog.csdn.net/zyplus/article/details/6672775 在JAVA中,是没有类似于PV操作.进程互斥等相关的方法的.JAVA的进程同步是通过syn ...
- java wait和notify及 synchronized sleep 总结
java 中线程我一直弄不清线程锁等 所以写了一些例子验证看法: 在这之前先看下API中wait中的解释: wait:方法来之java.lang.Objetc 方法翻译:在其他线程调用此对象的 not ...
- Java并发编程:Java中的锁和线程同步机制
锁的基础知识 锁的类型 锁从宏观上分类,只分为两种:悲观锁与乐观锁. 乐观锁 乐观锁是一种乐观思想,即认为读多写少,遇到并发写的可能性低,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新 ...
- Java中String做为synchronized同步锁使用详解
Java中使用String作同步锁 在Java中String是一种特殊的类型存在,在jdk中String在创建后是共享常量池的,即使在jdk1.8之后实现有所不同,但是功能还是差不多的. 借助这个特点 ...
- java 多线程并发 synchronized 同步机制及方式
2. 锁机制 3. 并发 Excutor框架 4. 并发性与多线程介绍 1. synchronized 参考1. synchronized 分两种方式进行线程的同步:同步块.同步方法 1. 方法同步 ...
- Java中String做为synchronized同步锁
synchronized (("" + userId).intern()) { // TODO:something } JVM内存区域里面有一块常量池,关于常量池的分配: JDK6 ...
- synchronized同步机制,修饰类和修饰对象的区别
synchronized用法 synchronized修饰的对象有几种: 修饰一个类:其作用的范围是synchronized后面括号括起来的部分,作用的对象是这个类的所有对象: 修饰一个方法:被修饰的 ...
- java中的synchronized同步代码块和同步方法的区别
下面这两段代码有什么区别? //下列两个方法有什么区别 public synchronized void method1(){} public void method2(){ synchronized ...
- java synchronized 同步详解
记下来,很重要. Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码. 一.当两个并发线程访问同一个对象object中的这个synchron ...
随机推荐
- 【原】为DevExpress的ChartControl添加Y轴控制 和 GridControl中指定列添加超级链接
一.控制ChartControl的Y轴范围 使用Devexpress中的CharControl控件,需要控制AxisY轴的显示范围,需要使用该控件的BoundDataChanged事件,具体代码如下: ...
- AI金融知识自学偏量化方向-了解不同类型的机器学习2
有监督学习 vs 无监督学习 迭代和评估 偏差方差权衡 结合有监督学习和无监督学习(半监督学习)
- 块级格式化上下文( Block formatting contexts)
那么如何触发BFC呢? float 除了none以外的值 overflow 除了visible 以外的值(hidden,auto,scroll ) display (table-cell,table- ...
- 319. Bulb Switcher
题目: There are n bulbs that are initially off. You first turn on all the bulbs. Then, you turn off ev ...
- 使用Delve进行Golang代码的调试
问题 安装好vscode编辑项目,出现以下错误: Failed to continue: "Cannot find Delve debugger. Ensure it is in your ...
- USI和USCI的区别
在 MSP430 系列中微控制器中有三种串行通讯模块.它们分别是 USART . USI 和 USCI . USART 支持同一硬件模块的两种串行模式,分别是 UART 和 SPI . USART 实 ...
- RedisLive监控工具 windows部署笔记
1. Python2.7环境安装 Path环境变量中添加 2.下载安装 VC Compiler for Python 地址: http://www.microsoft.com/en-us/dow ...
- 汉字 Unicode 编码范围
字符集 字数 Unicode 编码 基本汉字 20902字 4E00-9FA5 基本汉字补充 38字 9FA6-9FCB 扩展A 6582字 3400-4DB5 扩展B 42711字 20000-2A ...
- scrapy爬取某网站,模拟登陆过程中遇到的那些坑
本节内容 在访问网站的时候,我们经常遇到有些页面必须用户登录才能访问.这个时候我们之前写的傻傻的爬虫就被ban在门外了.所以本节,我们给爬虫配置cookie,使得爬虫能保持用户已登录的状态,达到获得那 ...
- javaWeb的基础知识
在服务器中,端口号是比较重要的,要学会查看和修改.win7有cmd和任务管理器两种方法.同时区分include动作和指令. <%@ include file="url"> ...