本文为原创文章,转载请注明出处
查看[Java]系列内容请点击:https://www.jianshu.com/nb/45938443
如果你不知道Java的重入锁等请参考:https://www.jianshu.com/p/ed96690edb86
在Java中synchronized
关键字用来控制同步,我们知道,synchronized
控制一段同步代码块的时候,需要在里面传入一个对象,JVM就会使用这个对象内置的锁机制来实现互斥锁,看如下代码,多线程顺序执行代码块:
public class Main {
private static Object lock = new Object();
public static void main(String[] args) throws Exception {
new Thread(new MyRunnable()).start();
new Thread(new MyRunnable()).start();
new Thread(new MyRunnable()).start();
}
private static class MyRunnable implements Runnable {
@Override
public void run() {
try {
synchronized (lock) { // 这里保证只有一个线程能进入
System.out.println("线程:" + Thread.currentThread().getId());
Thread.sleep(500);
System.out.println("线程:" + Thread.currentThread().getId());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
可以看到,虽然我们在不同的线程内都等待了一段时间,但是仍然是顺序执行的,执行结果:
线程:14
线程:14
线程:16
线程:16
线程:15
线程:15
那么,如何使得不按照顺序打印呢?
我们调整一下程序,使用wait
和notify
操作来进行:
public class Main {
private static Object lock = new Object();
private static int count = 3;
public static void main(String[] args) throws Exception {
new Thread(new MyRunnable()).start();
new Thread(new MyRunnable()).start();
new Thread(new MyRunnable()).start();
}
private static class MyRunnable implements Runnable {
@Override
public void run() {
try {
synchronized (lock) {
System.out.println("线程:" + Thread.currentThread().getId());
count--;
if (count > 0) lock.wait();
Thread.sleep(500);
System.out.println("线程:" + Thread.currentThread().getId());
lock.notify();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
运行结果:
线程:14
线程:16
线程:15
线程:15
线程:14
线程:16
可以看到,我们在synchronized
的内部调用了wait
使得当前线程休眠并且释放持有的锁,使得其他线程能进入synchronized
代码块执行。休眠的线程进入lock
对象的内部监视器等待队列等待执行。然后在lock.notify()
处唤醒这些代码继续竞争lock
锁并执行后续内容。