-
2019-06-23 18:23:24
首先,多线程中会使用到两个延迟的函数,wait和sleep。
wait是Object类中的方法,而sleep是Thread类中的方法。sleep是Thread类中的静态方法。无论是在a线程中调用b的sleep方法,还是b线程中调用a的sleep方法,谁调用,谁睡觉。
最主要的是sleep方法调用之后,并没有释放锁。使得线程仍然可以同步控制。sleep不会让出系统资源;
而wait是进入线程等待池中等待,让出系统资源。调用wait方法的线程,不会自己唤醒,需要线程调用 notify / notifyAll 方法唤醒等待池中的所有线程,才会进入就绪队列中等待系统分配资源。sleep方法会自动唤醒,如果时间不到,想要唤醒,可以使用interrupt方法强行打断。
Thread.sleep(0) // 触发操作系统立刻重新进行一次CPU竞争。
使用范围:
sleep可以在任何地方使用。而wait,notify,notifyAll只能在同步控制方法或者同步控制块中使用。
sleep必须捕获异常,而wait,notify,notifyAll的不需要捕获异常。更多相关内容 -
sleep和wait的区别,sleep会不会释放锁,notify和notifyAll的区别
2020-02-20 11:06:49wait会释放锁,sleep不会。 notify和notifyAll 通过wait使得线程挂起等待某个条件满足,当其他线程得运行使得这个条件满足时,就可以调用notify或者notifyAll来唤醒这个进程。他们都属于Object的方法。只能在同步块...sleep和wait
wait是Object的方法,wait是Thread的静态方法。
wait会释放锁,sleep不会。
notify和notifyAll
通过wait使得线程挂起等待某个条件满足,当其他线程得运行使得这个条件满足时,就可以调用notify或者notifyAll来唤醒这个进程。他们都属于Object的方法。只能在同步块或者同步方法中调用,否则会抛出illegalMonitorException。
当调用wait方法后,线程会进入拥有锁的对象的等待池中。等待池中的对象不会竞争该对象的锁。
当调用notify方法,便会有一个进程从等待池进入该对象的锁池,锁池中的对象可以竞争该对象的锁。而notifyAll会唤醒所有等待池中的线程进入锁池。
优先级高的线程拥有更大的概率通过竞争得到对象的锁,得到锁后该线程会继续执行,直到执行完synchronized的代码块,便会释放锁。没有竞争到锁的进程会留在锁池中,直到该线程重新调用wait方法它才会进入等待池。当锁被释放后,锁池中的线程会重新竞争。
锁池和等待池
等待池:线程A调用B对象的wait方法,它便会进入B的等待池中。
锁池:线程A已经拥有了对象B的锁,此时线程C想要调用B的synchronized方法(或代码块),就会进入B的锁池。
-
如何证明sleep不释放锁,而wait释放锁?
2021-02-13 00:50:11wait 加锁示例public class WaitDemo {private static Object locker = new Object();public static void main(String[] args) throws InterruptedException {WaitDemo waitDemo = new WaitDemo();// 启动新线程,...wait 加锁示例
public class WaitDemo {
private static Object locker = new Object();
public static void main(String[] args) throws InterruptedException {
WaitDemo waitDemo = new WaitDemo();
// 启动新线程,防止主线程被休眠
new Thread(() -> {
try {
waitDemo.doWait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
Thread.sleep(200); // 此行本身没有意义,是为了确保 wait() 先执行再执行 notify()
waitDemo.doNotify();
}
/**
* 执行 wait()
*/
private void doWait() throws InterruptedException {
synchronized (locker) {
System.out.println("wait start.");
locker.wait();
System.out.println("wait end.");
}
}
/**
* 执行 notify()
*/
private void doNotify() {
synchronized (locker) {
System.out.println("notify start.");
locker.notify();
System.out.println("notify end.");
}
}
}
以上程序的执行结果为:
wait start.
notify start.
notify end.
wait end.
代码解析
从上述代码可以看出,我们给 wait() 和 notify() 两个方法上了同一把锁(locker),但在调用完 wait() 方法之后 locker 锁就被释放了,所以程序才能正常执行 notify() 的代码,因为是同一把锁,如果不释放锁的话,是不会执行 notify() 的代码的,这一点也可以从打印的结果中证实(结果输出顺序),所以综合以上情况来说 wait() 方法是释放锁的。
sleep 加锁示例
public class WaitDemo {
private static Object locker = new Object();
public static void main(String[] args) throws InterruptedException {
WaitDemo waitDemo = new WaitDemo();
// 启动新线程,防止主线程被休眠
new Thread(() -> {
synchronized (locker) {
try {
System.out.println("sleep start.");
Thread.sleep(1000);
System.out.println("sleep end.");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
Thread.sleep(200);
waitDemo.doNotify();
}
/**
* 执行 notify()
*/
private void doNotify() {
synchronized (locker) {
System.out.println("notify start.");
locker.notify();
System.out.println("notify end.");
}
}
}
以上程序的执行结果为:
sleep start.
sleep end.
notify start.
notify end.
代码解析
从上述代码可以看出 sleep(1000) 方法(行号:11)执行之后,调用 notify() 方法并没有获取到 locker 锁,从上述执行结果中可以看出,而是执行完 sleep(1000) 方法之后才执行的 notify() 方法,因此可以证明调用 sleep() 方法并不会释放锁。
知识扩展
1.sleep 和 wait 有什么区别?
sleep 和 wait 几乎是所有面试中必问的题,但想完全回答正确似乎没那么简单。
对于 sleep 和 wait 的区别,通常的回答是这样的:
wait 必须搭配 synchronize 一起使用,而 sleep 不需要;
进入 wait 状态的线程能够被 notify 和 notifyAll 线程唤醒,而 sleep 状态的线程不能被 notify 方法唤醒;
wait 通常有条件地执行,线程会一直处于 wait 状态,直到某个条件变为真,但是 sleep 仅仅让你的线程进入睡眠状态;
wait 方法会释放对象锁,但 sleep 方法不会。
但上面的回答显然遗漏了一个重要的区别,在调用 wait 方法之后,线程会变为 WATING 状态,而调用 sleep 方法之后,线程会变为 TIMED_WAITING 状态。
2.wait 能不能在 static 方法中使用?为什么?
不能,因为 wait 方法是实例方法(非 static 方法),因此不能在 static 中使用,源码如下:
public final void wait() throws InterruptedException {
wait(0);
}
3.wait/notify 可以不搭配 synchronized 使用吗?为什么?
不行,因为不搭配 synchronized 使用的话程序会报错,如下图所示:
更深层次的原因是因为不加 synchronized 的话会造成 Lost Wake-Up Problem,唤醒丢失的问题,详情可见:https://juejin.im/post/5e6a4d8a6fb9a07cd80f36d1
总结
本文我们通过 synchronized 锁定同一对象,来测试 wait 和 sleep 方法,再通过执行结果的先后顺序证明:wait 方法会释放锁,而 sleep 方法并不会。同时我们还讲了几个 wait 和 sleep 的常见面试问题,希望本文可以帮助到你。
-
漫画:如何证明sleep不释放锁,而wait释放锁?
2020-07-21 09:44:38wait 加锁示例publicclassWaitDemo{ privatestaticObjectlocker=newObject(); public...wait 加锁示例
public class WaitDemo { private static Object locker = new Object(); public static void main(String[] args) throws InterruptedException { WaitDemo waitDemo = new WaitDemo(); // 启动新线程,防止主线程被休眠 new Thread(() -> { try { waitDemo.doWait(); } catch (InterruptedException e) { e.printStackTrace(); } }).start(); Thread.sleep(200); // 此行本身没有意义,是为了确保 wait() 先执行再执行 notify() waitDemo.doNotify(); } /** * 执行 wait() */ private void doWait() throws InterruptedException { synchronized (locker) { System.out.println("wait start."); locker.wait(); System.out.println("wait end."); } } /** * 执行 notify() */ private void doNotify() { synchronized (locker) { System.out.println("notify start."); locker.notify(); System.out.println("notify end."); } } }
以上程序的执行结果为:
wait start.
notify start.
notify end.
wait end.
代码解析
从上述代码可以看出,我们给
wait()
和notify()
两个方法上了同一把锁(locker),但在调用完wait()
方法之后locker
锁就被释放了,所以程序才能正常执行notify()
的代码,因为是同一把锁,如果不释放锁的话,是不会执行notify()
的代码的,这一点也可以从打印的结果中证实(结果输出顺序),所以综合以上情况来说wait()
方法是释放锁的。sleep 加锁示例
public class WaitDemo { private static Object locker = new Object(); public static void main(String[] args) throws InterruptedException { WaitDemo waitDemo = new WaitDemo(); // 启动新线程,防止主线程被休眠 new Thread(() -> { synchronized (locker) { try { System.out.println("sleep start."); Thread.sleep(1000); System.out.println("sleep end."); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); Thread.sleep(200); waitDemo.doNotify(); } /** * 执行 notify() */ private void doNotify() { synchronized (locker) { System.out.println("notify start."); locker.notify(); System.out.println("notify end."); } } }
以上程序的执行结果为:
sleep start.
sleep end.
notify start.
notify end.
代码解析
从上述代码可以看出
sleep(1000)
方法(行号:11)执行之后,调用notify()
方法并没有获取到 locker 锁,从上述执行结果中可以看出,而是执行完sleep(1000)
方法之后才执行的notify()
方法,因此可以证明调用sleep()
方法并不会释放锁。知识扩展
1.sleep 和 wait 有什么区别?
sleep
和wait
几乎是所有面试中必问的题,但想完全回答正确似乎没那么简单。对于
sleep
和wait
的区别,通常的回答是这样的:wait 必须搭配 synchronize 一起使用,而 sleep 不需要;
进入 wait 状态的线程能够被 notify 和 notifyAll 线程唤醒,而 sleep 状态的线程不能被 notify 方法唤醒;
wait 通常有条件地执行,线程会一直处于 wait 状态,直到某个条件变为真,但是 sleep 仅仅让你的线程进入睡眠状态;
wait 方法会释放对象锁,但 sleep 方法不会。
但上面的回答显然遗漏了一个重要的区别,在调用
wait
方法之后,线程会变为WATING
状态,而调用sleep
方法之后,线程会变为TIMED_WAITING
状态。2.wait 能不能在 static 方法中使用?为什么?
不能,因为
wait
方法是实例方法(非static
方法),因此不能在static
中使用,源码如下:public final void wait() throws InterruptedException { wait(0); }
3.wait/notify 可以不搭配 synchronized 使用吗?为什么?
不行,因为不搭配
synchronized
使用的话程序会报错,如下图所示:更深层次的原因是因为不加
synchronized
的话会造成 Lost Wake-Up Problem,唤醒丢失的问题,详情可见:https://juejin.im/post/5e6a4d8a6fb9a07cd80f36d1总结
本文我们通过
synchronized
锁定同一对象,来测试wait
和sleep
方法,再通过执行结果的先后顺序证明:wait
方法会释放锁,而sleep
方法并不会。同时我们还讲了几个wait
和sleep
的常见面试问题,希望本文可以帮助到你。
关注下方二维码,每一天都有干货!
-
多线程中的wait与sleep到底谁释放了锁?
2021-03-08 23:09:26转载自:https://www.cnblogs.com/yigechengxuyuan/p/8398647.html首先,多线程中会使用到两个延迟的函数,wait和sleep。wait是Object类中的方法,而sleep是Thread类中的方法。sleep是Thread类中的静态方法。无论是... -
wait和sleep的区别,Synchronized锁和lock锁的区别你真的搞懂了吗?
2021-04-21 10:24:00wait 会释放锁 sleep 睡觉了,抱着锁睡觉,不会释放! 3、使用的范围是不同的 wait 必须在同步代码块中使用 sleep 可以再任何地方睡眠 没错,sleep它就是校长,想在那儿睡就在那儿睡! 二:Synchronized锁和lock锁 ... -
Java中sleep()与wait()区别(涉及类锁相关概念)
2021-03-08 23:08:35在区别之前,我们首先先了解一下关于对象锁,类锁的相关概念(当时查阅的详细地址:http://www.importnew.com/20444.html,该作者对类锁和对象锁进行了详细的举例分析)对象锁,类锁在java虚拟机中,每个对象和类在... -
sleep 不会释放锁,但是会让出cpu执行权
2021-01-27 11:05:08public static native void sleep(long millis)方法显然是Thread的静态方法,很显然它是让当前线程按照指定的时间休眠,其休眠时间的精度取决于处理器的计时器和调度器。需要注意的是如果当前线程获得了锁,sleep... -
sleep不会释放锁,但是会让出cpu执行权
2020-06-03 15:58:29sleep和wait方法的区别就是sleep不会释放锁,当睡眠的时间到了之后,线程会自动进入可执行状态,等待cpu的执行。而wait方法会释放锁(所以前提就是线程在执行wait方法之前必须要获得锁,也就意味着只能在同步方法... -
C#中sleep和wait的区别分析
2021-01-20 06:54:04本文较为详细的分析了C#中sleep和wait的区别。分享给大家供大家参考。具体分析如下: sleep和wait都是使线程暂时停止执行的方法,但它们有很大的不同。 ①. sleep是线程类Thread 的方法,它是使当前线程暂时睡眠,... -
sleep和wait的区别
2021-04-26 18:08:591、这两个方法来自不同的类分别是,sleep来自Thread类,和wait来自Object类...2、最主要是sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。sleep不出让系统资源;wait是进入线程... -
Thread wait和sleep的区别
2019-07-11 17:25:25sleep()是让某个线程暂停运行一段时间,其控制范围是由当前线程决定,也就是说,在线程里面决定.好比如说,我要做的事情是 "点火->烧水->煮面",而当我点完火之后我不立即烧水,我要休息一段时间再烧.对于运行的主动... -
wait会释放锁?当然会释放锁,代码见真招!!!
2021-02-17 23:58:07我在网上看到很多人错误的理解,认为wait不会释放锁,然而它们并没有任何理由,仅凭自己的认知,然后很骄傲的和人讲,wait不会释放锁,你这是误人子弟。殊不知他自己才是误人子弟。 我先讲一讲原理,然后用代码来... -
Android Sleep和Wait区别
2021-06-09 05:56:15sleep是Thread的静态类方法,谁调用的谁去睡觉,即使是在a线程离调用了b的sleep方法,实际上还是a 去睡觉,要让b去睡觉要在b的代码中调用sleep.2、最主要是sleep方法没有释放锁,而wait方法释放了锁,使其他线程可以... -
java sleep、wait加锁对象与锁释放
2019-08-07 01:01:38以上两步分析了sleep不会释放线程自身的锁,看似sleep释放了它操作的对象book实例的对象锁,但是真的释放了吗?我们是在t1线程的run函数里面,add()函数之后,调用的t1的sleep。此时add函数执行完毕才会去调用... -
代码证明使用wait()休眠的线程会释放锁,使用sleep()休眠的线程不会释放锁
2020-06-22 10:59:22设计一个程序证明使用wait()休眠的线程会释放锁,使用sleep()休眠的线程不会释放锁 证明使用wait()休眠的线程会释放锁 package proveWaitAndSleep; import java.io.Serializable; public class Animal implements... -
线程通讯、wait和sleep 区别?sleep(0) vs wait(0)有什么区别
2021-05-07 20:53:20文章目录什么是线程通讯wait和sleep 区别?(面试题)sleep(0) vs wait(0)有什么区别?为什么wait会释放锁?而sleep不会释放锁?为什么wait是 0bject的方法,而sleep是Thread 的方法? 什么是线程通讯 线程通讯就是一个... -
JAVA中的wait和sleep有什么区别?
2021-05-15 13:13:002、最主要是sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。 3、wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用(使用范围) 4... -
在java中wait和sleep方法的不同
2020-01-17 11:16:16最大的不同是在等待时wait会释放锁,而sleep一直持有锁。Wait通常被用于线程间交互,sleep通常被用于暂停执行。 在Java中线程的状态一共被分成6种: 初始态: 创建一个Thread对象,但还未调用start()启动线程时... -
wait方法会释放同步块里的所有锁么?
2020-02-28 18:31:06示例代码 public class TestMain { //对象锁一 private static Object lock1 = new Object(); //对象锁二 private static Object lock2 = new Object(); public static void main(String[] args) throws ... -
Java sleep和wait的区别
2018-04-05 10:44:18sleep() 方法 wait() 方法 sleep()使当前线程进入停滞状态(阻塞当前线程),...当一个线程执行到wait()方法时,它就进入到一个和该对象相关的等待池中,同时失去(释放)了对象的机锁(暂时失去机锁,wait(l... -
Java中wait和sleep方法的区别
2019-03-01 10:48:132.最主要是sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法(锁代码块和方法锁)。 3.wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方... -
线程的四种状态以及wait和sleep的区别
2018-08-20 13:42:313.正因为wait方法会释放锁,所以调用该方法时,当前的线程必须拥有当前对象的monitor,也即lock,就是锁。要确保调用wait()方法的时候拥有锁,即,wait()方法的调用必须放在synchronized方法或synchronized块中。 ... -
Java同步锁何时释放?
2021-02-28 08:50:52由于等待一个锁定线程只有在获得这把...3. 在执行同步代码块的过程中,执行了锁所属对象的wait()方法,这个线程会释放锁,进行对象的等待池。除了以上情况外,只要持有锁的此案吃还没有执行完同步代码块,就不会释放... -
wait与sleep的区别
2018-04-21 01:32:461、wait()方法属于Object类,sleep()属于Thread类; 2、wait()方法释放cpu给其他线程,自己让出资源进入等待池等待;...4、wait()方法会释放持有的锁,不然其他线程不能进入同步方法或同步块,从而不能调用no... -
Threed.sleep是不会释放锁,而wait是释放锁的(对象锁)
2017-08-11 12:45:00实战分析 一直都说,Threed.sleep是不会释放锁,而wait是释放锁的(对象锁),现理论上来分析一下啊。 v package thread.concurrent; public class DeepenSleep implements ...