Synchronized 精讲 (3)

输出结果: 线程 t1 和线程 t2 执行形成了顺序

图片

3.性质 3.1 可重入性也叫递归锁

就是说你已经获取了一把锁,等想要再次请求的时候不需要释放这把锁和其他线程一起竞争该锁,可以直接使用该锁

好处:避免死锁

粒度:线程而非调用

3.2案例证明可重入性

证明同一个方法是可重入

代码实例:

package synchronizedPage; public class SynchronizedDemo6 { int count = 0; public static void main(String[] args) { SynchronizedDemo6 synchronizedDemo6 = new SynchronizedDemo6(); synchronizedDemo6.method(); } private synchronized void method() { System.out.println(count); if (count == 0) { count++; method(); } } }

输出结果:

在这里插入图片描述

证明可重入不要求是同一个方法

代码实例:

package synchronizedPage; public class SynchronizedDemo7 { private synchronized void method1() { System.out.println("method1"); method2(); } private synchronized void method2() { System.out.println("method2"); } public static void main(String[] args) { SynchronizedDemo7 synchronizedDemo7 = new SynchronizedDemo7(); synchronizedDemo7.method1(); } }

输出结果:

在这里插入图片描述

证明可重入不要求是同一个类中的

代码实例:

package synchronizedPage; public class SynchronizedDemo8 { public synchronized void doSomething() { System.out.println("我是父类方法"); } } class childrenClass extends SynchronizedDemo8{ public synchronized void doSomething() { System.out.println("我是子类方法"); super.doSomething(); } public static void main(String[] args) { childrenClass childrenClass = new childrenClass(); childrenClass.doSomething(); } }

输出结果:

图片

3.3 不可中断

当A线程持有这把锁时,B线程如果也想要A线程持有的锁时只能等待,A永远不释放的话,那么B线程永远的等待下去。

4.底层原理实现 4.1 加锁和释放锁的原理

synchronized加在代码块上

public void test() { synchronized(this){ count++; } }

利用 javap -verbose 类的名字查看编译后的文件

在这里插入图片描述

monitorenter:每个对象都是一个监视器锁(monitor)。当monitor被占用时就会处于锁定状态,线程执行monitorenter指令时尝试获取monitor的所有权,过程如下:

如果monitor的进入数为0,则该线程进入monitor,然后将进入数设置为1,该线程即为monitor的所有者

如果线程已经占有该monitor,只是重新进入,则进入monitor的进入数加1【可重入性质

如果其他线程已经占用了monitor,则该线程进入阻塞状态,直到monitor的进入数为0,再重新尝试获取monitor的所有权

monitorexit:执行monitorexit的线程必须是objectref所对应的monitor的所有者。指令执行时,monitor的进入数减1,如果减1后进入数为0,那线程退出monitor,不再是这个monitor的所有者。其他被这个monitor阻塞的线程可以尝试去获取这个 monitor 的所有权

monitorexit指令出现了两次,第1次为同步正常退出释放锁;第2次为发生异步退出释放锁

synchronized加在方法上(无论时普通方法还是静态方法)

public synchronized void test() { count++; }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpjdfy.html