Synchronized同步原理
- 1. synchronized的使用?
- 2. 如何保证线程安全的?
- 3.可重入原理(加锁次数计数器)
- 4. 原子性和可见性(顺序性)
1. synchronized的使用?
- 对象锁
- 方法锁
- 类锁
2. 如何保证线程安全的?
public class SynchronizedDemo2 {Object object = new Object();public void method1() {synchronized (object) {}}
}
执行javac SynchronizedDemo2.java, javap -verbose SynchronizedDemo2.class
下图表现了对象,对象监视器,同步队列以及执行线程状态之间的关系:
该图可以看出,任意线程对Object的访问,首先要获得Object的监视器,如果获取失败,该线程就进入同步状态,线程状态变为BLOCKED,当Object的监视器占有者释放后,在同步队列中得线程就会有机会重新获取该监视器。
3.可重入原理(加锁次数计数器)
public class SynchronizedDemo {public static void main(String[] args) {synchronized (SynchronizedDemo.class) {}method2();}private synchronized static void method2() {}
}
public static void main(java.lang.String[]);descriptor: ([Ljava/lang/String;)Vflags: (0x0009) ACC_PUBLIC, ACC_STATICCode:stack=2, locals=3, args_size=10: ldc #2 // class tech/pdai/test/synchronized/SynchronizedDemo2: dup3: astore_14: monitorenter5: aload_16: monitorexit7: goto 1510: astore_211: aload_112: monitorexit13: aload_215: invokestatic #3 // Method method2:()VException table:from to target type5 7 10 any10 13 10 any
Synchronized先天具有重入性。每个对象拥有一个计数器,当线程获取该对象锁后,计数器就会加一,释放锁后就会将计数器减一。
4. 原子性和可见性(顺序性)
- 保证可见性的原理:内存模型和happens-before规则
- Synchronized的happens-before规则,即监视器锁规则:对同一个监视器的解锁,happens-before于对该监视器的加锁。继续来看代码:
public class MonitorDemo {private int a = 0;public synchronized void writer() { // 1a++; // 2} // 3public synchronized void reader() { // 4int i = a; // 5} // 6
}
该代码的happens-before关系如图所示:
在图中每一个箭头连接的两个节点就代表之间的happens-before关系,黑色的是通过程序顺序规则推导出来,红色的为监视器锁规则推导而出:
线程A释放锁happens-before线程B加锁,蓝色的则是通过程序顺序规则和监视器锁规则推>测出来happens-befor关系,通过传递性规则进一步推导的happens-before关系。现在我们来重点关注2 happens-before 5,通过这个关系我们可以得出什么?根据happens-before的定义中的一条:如果A happens-before B,则A的执行结果对B可见,并且A的执行顺序先于B。线程A先对共享变量A进行加一,由2 happens-before 5关系可知线程A的执行结果对线程B可见即线程B所读取到的a的值为1。