-
2021-04-21 08:59:21
1.sleep()方法
在指定时间内让当前正在执行的线程暂停执行,但不会释放“锁标志”。不推荐使用。
sleep()使当前线程进入阻塞状态,在指定时间内不会执行。
2.wait()方法
在其他线程调用对象的notify或notifyAll方法前,导致当前线程等待。线程会释放掉它所占有的“锁标志”,从而使别的线程有机会抢占该锁。
当前线程必须拥有当前对象锁。如果当前线程不是此锁的拥有者,会抛出IllegalMonitorStateException异常。
唤醒当前对象锁的等待线程使用notify或notifyAll方法,也必须拥有相同的对象锁,否则也会抛出IllegalMonitorStateException异常。
waite()和notify()必须在synchronized函数或synchronized block中进行调用。如果在non-synchronized函数或non-synchronized block中进行调用,虽然能编译通过,但在运行时会发生IllegalMonitorStateException的异常。
3.yield方法
暂停当前正在执行的线程对象。
yield()只是使当前线程重新回到可执行状态,所以执行yield()的线程有可能在进入到可执行状态后马上又被执行。
yield()只能使同优先级或更高优先级的线程有执行的机会。
4.join方法
等待该线程终止。
等待调用join方法的线程结束,再继续执行。如:t.join();//主要用于等待t线程运行结束,若无此句,main则会执行完毕,导致结果不可预测。
join()底层就是调用wait()方法的,wait()释放锁资源,故join也释放锁资源
1.sleep会使当前线程睡眠指定时间,不释放锁
2.yield会使当前线程重回到可执行状态,等待cpu的调度,不释放锁
3.wait会使当前线程回到线程池中等待,释放锁,当被其他线程使用notify,notifyAll唤醒时进入可执行状态
4.当前线程调用 某线程.join()时会使当前线程等待某线程执行完毕再结束,底层调用了wait,释放锁更多相关内容 -
Java并发编程:锁的释放
2021-02-12 15:13:26在讲锁的释放前,我们先讲一下线程的三种主要状态:运行、就绪(可运行)、阻塞。当然,除了这个之外,肯定还有初始状态和结束状态,那个就不讨论了。当我们创建线程之后,还只是进入初始状态,如果我们调用run()方法...在讲锁的释放前,我们先讲一下线程的三种主要状态:运行、就绪(可运行)、阻塞。当然,除了这个之外,肯定还有初始状态和结束状态,那个就不讨论了。
当我们创建线程之后,还只是进入初始状态,如果我们调用run()方法运行,根本就不会启动新的线程。当调用start()后,可以将线程状态改为可运行状态,然后,由操作系统来决定调用哪个线程。当幸运的被操作系统选中之后,就可以进入真正的运行状态了。当运行当时间片用完,或者调用yield()礼让方法,就会把当前当执行权交出来,进入可运行就绪状态。如果在运行的过程中,有系统IO,如等待输入,弹出确认对话框等,则会使当前线程进入阻塞状态,动弹不得。只有等待用户操作之后,才能往下进行。sleep()方法和join()方法可以可以达到类似的阻塞效果。
然后,我们把对象锁部分的状态也加进来。当我们使用synchronized修饰方法或者代码块时,会获取对象的锁,并进入获取该对象锁的等待池,由操作系统来决定调用哪个线程(非公平锁)。当获取到该对象锁之后,就可以进入可运行状态了。
另外,还有一个对象的wait()方法,可以使线程放弃持有的该对象锁,并进入通知等待状态。当其他线程调用等待线程需要的对象的notify()或者notifyAll()方法时,该线程重新进入获取对象锁的队列中参与锁的获取。
-
java线程join方法会释放锁吗
2021-08-25 11:24:36java线程join方法会释放锁吗,虽然join底层使用wait,wait是释放锁的 但当给对象加锁,wait释放的锁是对象的锁,可以认为释放锁 当给线程加锁,wait释放的锁是线程的锁,此时认为不释放锁 wait()和join()的...java线程join方法会释放锁吗,虽然join底层使用wait,wait是释放锁的
wait()和join()的调用方的区别:
object.wait()和thread.join()
join()的底层确实是wait(),wait()也确实释放锁,但是释放的是thread的对象锁
也就可以这么说
synchronized(obj){ thread.join(); //join不释放锁 } synchronized(thread){ thread.join(); //join释放锁 }
下面是具体的例子:
public class JoinTest { public static void main(String[] args) { Object oo = new Object(); MThread thread1 = new MThread("thread1 -- ", oo); thread1.start(); // synchronized (thread1) synchronized (oo) { for (int i = 0; i < 100; i++) { if (i == 20) { try { thread1.join(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(Thread.currentThread().getName() + " -- " + i); } } } } class MThread extends Thread { private String name; private Object oo; public MThread(String name, Object oo) { this.name = name; this.oo = oo; } @Override public void run() { synchronized (oo) { for (int i = 0; i < 100; i++) { System.out.println(name + i); } } } }
注意:上面代码是在i==20时加锁
当给对象oo加锁时,不释放锁(释放的是线程对象的锁而不是对象oo的锁),到20就卡住了
当给线程Thread1加锁时,释放锁
-
如何证明sleep不释放锁,而wait释放锁?
2021-02-13 00:50:11是不会执行 notify() 的代码的,这一点也可以从打印的结果中证实(结果输出顺序),所以综合以上情况来说 wait() 方法是释放锁的。 sleep 加锁示例 public class WaitDemo { private static Object locker = new ...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 的常见面试问题,希望本文可以帮助到你。
-
java锁的释放与建立
2013-03-12 13:05:13详细讲解了java锁的原理,里面还带有对应的图,详细讲解!有一个简单的程序,可以自己去分析! -
java线程类的join方法是否会释放锁,网上很多人说不释放锁,但是join底层使用wait,wait是释放锁的
2018-10-09 15:09:35java线程类的join方法是否会释放锁,网上很多人说不释放锁,但是join底层使用wait,wait是释放锁的 -
JAVA基础-多线程和锁
2021-01-13 19:14:32线程的基本流程image.png如何中断一个线程方法一:调用interrupt方法,通知线程应该中断了:A.如果线程处于被阻塞状态,那么线程将立即退出被阻塞状态,并抛出了一个InterruptedException异常。...对象锁和类... -
Java线程之释放锁,释放资源,释放CPU
2021-02-26 19:43:36多线程中的wait与sleep到底谁释放了锁首先,多线程中会使用到两个延迟的函数,wait和sleep。wait是Object类中的方法,而...最主要的是sleep方法调用之后,并没有释放锁。使得线程仍然可以同步控制。sleep不会让出... -
39.线程间的通信-wait与notify-wait方法自动释放锁与notify方法不会释放锁.mp4
2020-04-06 20:31:30在学习Java过程中,自己收集了很多的Java的学习资料,分享给大家,有需要的欢迎下载,希望对大家有用,一起学习,一起进步。 -
java synchronized同步锁的释放时机
2020-09-28 19:33:021.当前线程的同步方法、代码块执行结束的时候释放。 2.当前线程在同步方法、同步代码块中遇到break 、 return 终于该代码块或者方法的时候释放。...4.程序执行了 同步对象 wait 方法 ,当前线程暂停,释放锁 ... -
在Java中使用redis分布式锁,业务逻辑跨多个方法,怎么释放分布式锁
2020-07-07 12:09:32lock(){//并发下单加分布式锁 //判断是否有下单资格 是否超过每日下单数 if(true){ return true; }else{ return false; } } }; validate(){};//参数校验之类的 after(){ redis.inrc();//统计每日下... -
Java锁机制Lock用法示例
2020-08-27 00:58:00主要介绍了Java锁机制Lock用法,结合具体实例形式分析了Java锁机制的相关上锁、释放锁、隐式锁、显式锁等概念与使用技巧,需要的朋友可以参考下 -
java多线程学习之——多线程中几种释放锁和不释放锁的操作
2017-08-12 18:34:46在学习java多线程这一块知识的时候,遇到了很多个关于线程锁什么时候释放的问题,现总结几种释放锁和不释放锁的操作如下 -
java多线程什么时候释放锁
2019-05-12 20:52:47由于等待一个锁定线程只有在获得这把锁之后,才能恢复运行,所以让持有锁的线程在不需要锁的时候及时释放锁是很重要的。在以下情况下,持有锁的线程会释放锁: 1、当前线程的同步方法、代码块执行结束的时候释放 ... -
【18】java锁之wait,notify(wait会释放锁,notify仅仅只是通知,不释放锁)
2017-03-18 00:57:00wait是指在一个已经进入了同步锁的线程内,让自己暂时让出同步锁,以便其他正在等待此锁的线程可以得到同步锁并运行,只有其他线程调用了notify方法(notify并不释放锁,只是告诉调用过wait方法的线程可以去参与获得... -
java高并发、多线程(八)--LockSupport.park()会释放锁吗?
2020-06-09 20:41:50java高并发、多线程(八) public class LockSupportTest { public synchronized void m1(){ System.out.println("m1 start"); LockSupport.park(); System.out.println("m1 end"); } public synchronized ... -
java多线程中Object.wait()和Condition.await()是否会释放当前线程锁占有的锁
2021-03-09 21:52:53我刚开始深入研究多线程,一直认为Object.wait()/Condition.await()让当前线程阻塞的同时,也会释放当前线程对该condition对象的锁。在之前的一些测试代码中也显示wait后,线程上的锁被释放了。但是我们经理却坚持... -
java中,synchronized释放锁的时机
2018-01-08 15:22:44在程序中,是无法显式释放对同步监视器的锁的,而会在如下几个情况下释放锁。 1、当前线程的同步方法、代码块执行结束的时候释放 2、当前线程在同步方法、同步代码块中遇到break 、 return 终于该代码块或者... -
wait会释放锁?当然会释放锁,代码见真招!!!
2021-02-17 23:58:07我在网上看到很多人错误的理解,认为wait不会释放锁,然而它们并没有任何理由,仅凭自己的认知,然后很骄傲的和人讲,wait不会释放锁,你这是误人子弟。殊不知他自己才是误人子弟。 我先讲一讲原理,然后用代码来... -
Java乐观锁%悲观锁
2021-11-16 09:30:59尝试去获得一把锁,无论获得还是无法获得立刻返回True/False 不会阻塞进程,使用此锁可在获取锁的过程中完成其它操作。如下例子演示了在线程1获得了锁之后,线程2使用trylock()可以初始化一些参数,缺点是这里比较... -
java多线程什么时候释放锁—wait()、notify()
2019-04-10 12:23:12由于等待一个锁定线程只有在获得这把锁之后,才能恢复运行,所以让持有锁的线程在不需要锁的时候及时释放锁是很重要的。在以下情况下,持有锁的线程会释放锁: 1. 执行完同步代码块。 2. 在执行同步代码块的过程中... -
多线程中的wait与sleep到底谁释放了锁?
2021-03-08 23:09:26最主要的是sleep方法调用之后,并没有释放锁。使得线程仍然可以同步控制。sleep不会让出系统资源; 而wait是进入线程等待池中等待,让出系统资源。 调用wait方法的线程,不会自己唤醒,需要线程调用 notify / ... -
java锁
2021-04-24 09:15:021.悲观锁 :锁住资源其他线程不能在访问 2.乐观锁: 不锁资源,默认其他进程不会修改资源 锁住同步资源失败 线程是否需要阻塞? 阻塞 不阻塞: 自旋锁 适应性自旋锁 减少了线程上下文的其二环 因为是不阻塞 ... -
Java 独占锁与共享锁、公平锁与非公平锁、可重入锁
2021-12-18 17:57:44缺点就是不公平,在某些场景中,特别是每次获取锁后会迅速执行并且释放锁的情况下,非公平锁是可以使用的。假设你洗澡的时间巨长,还有人插我队,这谁能忍得了? 可重入锁 可重入锁的概念很多人容易理解错,他是指... -
Java 读写锁的实现
2021-02-12 09:46:08一、synchronized和ReentrantLock的对比到现在,看到多线程中,锁定的方式有2种:synchronized...一样,是语法层面的实现,因此synchronized获取锁以及释放锁都是Java虚拟机帮助用户完成的;ReentrantLock是类层面的... -
Java中sleep()与wait()区别(涉及类锁相关概念)
2021-03-08 23:08:35在区别之前,我们首先先了解一下关于对象锁,类锁的相关概念(当时查阅的详细地址:http://www.importnew.com/20444.html,该作者对类锁和对象锁进行了详细的举例分析)对象锁,类锁在java虚拟机中,每个对象和类在... -
Java实现锁的几种方式
2021-03-16 22:41:00锁和同步,学习多线程避不开的两个问题,Java提供了synchronized关键字来同步方法和代码块,还提供了很多方便易用的并发工具类,例如:LockSupport、CyclicBarrier、CountDownLatch、Semaphore…有没有想过自己实现...