一.synchronized的简单介绍
public class TicketWindowRunnable implements Runnable {
private int index = 1;
private final static int MAX = 500;
private final Object MONITOR = new Object();
@Override
public void run() {
while (true) {
//1
synchronized (MONITOR) {
if (index > MAX)
break;
try {
Thread.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread() + " 的号码是:" + (index++));
}
//2
}
}
}
1.从上面代码,可以了解到多个线程同时执行,不会发生超卖的现象,即index最终值不会超过MAX。
2.为什么会保证不会发生超卖的现象,因为synchronized,多个线程会竞争 MONITOR锁,拿到MONITOR锁的线程才有资格执行同步代码块里的代码,当持有 MONITOR锁执行完后,会放弃 MONITOR锁,其他线程才有资格再次竞争MONITOR锁
3.synchronized里代码块,会使index++的修改对其他线程可见,这里你需要了解JMM
二.理解synchronized运行机制
-
当一个线程竞争到 MONITOR锁时,其他线程进入某个队列中,待同步代码块执行完后,MONITOR锁会释放,队列中的线程可再次竞争
-
从线程状态来说,等待某个线程释放MONITOR锁的线程,状态为BLOCKED,进入阻塞队列
(1)使用jconsole可以了解到
(2)使用jstack
- 从字节码的角度,MONITOR锁实现机制是moinitorenter和monitorexit
- 从字节码的角度,MONITOR锁实现机制是moinitorenter和monitorexit
三.synchronized应用场景
-
修饰实例方法,作用于当前实例加锁,进入同步代码前要获得当前实例的锁
-
修饰静态方法,作用于当前类对象加锁,进入同步代码前要获得当前类对象的锁
-
修饰代码块,指定加锁对象,对给定对象加锁,进入同步代码库前要获得给定对象的锁
-
this锁和class锁