我在网上看到很多人错误的理解,认为wait不会释放锁,然而它们并没有任何理由,仅凭自己的认知,然后很骄傲的和人讲,wait不会释放锁,你这是误人子弟。殊不知他自己才是误人子弟。
我先讲一讲原理,然后用代码来证明它,让那些还认为wait不会释放锁的同志闭嘴。赶紧改错还来的及
原理
其实很好理解,从设计的角度很容易分析出wait是会释放锁的。
线程在运行的时候占用了计算机的共享资源,因为当前线程在使用它,然而当前线程进行了休眠例如 wait()
很浅显的道理,当前线程已经停止了,那意味着这个资源空闲了下来。那么作为万恶的剥削者"程序员"
肯定不会让这个资源空闲着,你们说对吧!!!
因此很容易推断出wait()
是会释放锁的,而锁的奥义就是控制指定的线程持有共享资源,既然线程都进行了等待,肯定是要需要释放锁的!!!
贴代码前我先讲一下怎么用代码进行证明
很简单,用两个线程同时用一把锁,其中一个线程先执行,并且进行wait()
,如果释放了锁,那么是不是对于另外一个线程来说它就可以抢占到这个锁呢(因为它空闲下来了)
而我的代码中为了让两个线程实现这种效果,我让一个线程等待一秒
代码
import java.util.concurrent.TimeUnit;
public class Demo {
public static void main(String[] args) {
Object object=new Object();
final Thread thread1 = new Thread(() -> {
System.out.println("线程1开始");
synchronized (object) {
try {
object.wait();// 进行阻塞,并且释放对象锁
System.out.println("====线程1");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("线程1结束");
});
final Thread thread2 = new Thread(() -> {
System.out.println("线程2开始");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (object){
System.out.println("线程2=======");
}
System.out.println("线程2结束");
});
thread1.start();
thread2.start();
}
}
运行结果
从结果中很明显发现 wait()
方法会让当前线程释放锁,而线程2等了1s
后,因为线程1释放了锁,因此线程2就能抢占到。
继续证明线程2的synchronized (object)
在没有获取锁的情况下是会阻塞等待锁释放
代码2
import java.util.concurrent.TimeUnit;
public class Demo {
public static void main(String[] args) {
Object object=new Object();
final Thread thread1 = new Thread(() -> {
System.out.println("线程1开始");
synchronized (object) {
try {
TimeUnit.SECONDS.sleep(2000); // 等待足够长时间让我们足以观察到结果
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("====线程1");
}
System.out.println("线程1结束");
});
final Thread thread2 = new Thread(() -> {
System.out.println("线程2开始");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (object){
System.out.println("线程2=======");// 输出这一句说明当前线程抢占到了锁
}
System.out.println("线程2结束");
});
thread1.start();
thread2.start();
}
}