synchronized关键字的性质
1.可重入:同一线程的外层函数获得锁之后,内层函数可直接再次获得该锁,好处:避免死锁,提升封装性
证明可重入粒度:1、同一个方法是可重入的
2、可重入不要求是同一个方法
3、可重入不要求是同一个类
可重入原理:加锁次数计数器
-
-
- JVM负责跟踪对象被加锁的次数;
- 线程第一次给对象加锁的时候计数变为1,每当这个相同的线程在这个对象上加锁时,计数递增;
- 每当任务离开时,计数会减1,计数为0时,锁被完全释放。
-
2.不可中断:如果一个线程拿到一把锁,另一个线程要想获得这把锁,只能等待或者阻塞,直到别的线程释放这个锁,如果另一个线程一直不释放,那就只能一直等待下去。(相比之下,Lock类拥有中断的能力:1.lock如果等的时间太长,有权利中断当前获得锁的这个线程;2.lock等待时间太长不想等,可以自动退出)
同一个方法是可重入的:
递归调用method方法打印出a=1;就说明进入该方法两次
/** * * 验证synchronized的可重入性质1: * 同一个方法是可重入的 * @author Administrator * */ public class SynchronizeTest04 implements Runnable{ static SynchronizeTest04 instance1 = new SynchronizeTest04(); int a = 0; @Override public void run() { //调用加synchronized关键字的普通方法 method(); } public synchronized void method() { System.out.println("a="+a); if(a==0) { a++; method(); } } public static void main(String[] args) { Thread t1 = new Thread(instance1,"线程一"); t1.start(); while(t1.isAlive()) { } System.out.println("执行结束"); } }
可重入不要求是同一个方法:
run方法中调用被synchronized修饰的method1方法,在method1中调用被synchronized修饰的method2方法
/** * * 验证synchronized的可重入性质2: * 可重入不要求是同一个方法 * @author Administrator * */ public class SynchronizeTest04 implements Runnable{ static SynchronizeTest04 instance1 = new SynchronizeTest04(); int a = 0; @Override public void run() { //调用加synchronized关键字的普通方法 method1(); } public synchronized void method1() { System.out.println("我是方法一"); method2(); } public synchronized void method2() { System.out.println("我是方法二"); } public static void main(String[] args) { Thread t1 = new Thread(instance1,"线程一"); t1.start(); while(t1.isAlive()) { } System.out.println("执行结束"); } }
可重入不要求是同一个方法
可重入不要求是同一个类:
由于main方法就是一个线程,所以这里用main方法演示,父类中创建被synchronized修饰的doSomething方法,子类中重写doSomething方法,并调用父类方法
/** * * 验证synchronized的可重入性质3: * 可重入不要求是同一个类 * @author Administrator * */ public class SynchronizeTest05 { public synchronized void doSomething() { System.out.println("我是父类"); } public static void main(String[] args) { Test t = new Test(); t.doSomething(); } } class Test extends SynchronizeTest05{ //重写父类的方法,并调用父类方法 public synchronized void doSomething() { System.out.println("我是子类"); super.doSomething(); } }
可重入不要求是同一个类
synchronized关键字的缺点:
1、效率低:锁的释放少,试图获得锁时不能设置超时,不能中断一个正在获得锁的线程;
2、不够灵活:加锁和释放的时机单一,每个锁仅有单一的条件
3、无法知道是否成功获取到锁
在使用synchronized关键字时注意:锁对象不能为空、锁的作用域不宜过大、避免死锁。
原文地址:https://www.cnblogs.com/YpfBolg/p/10805794.html
时间: 2024-10-01 04:21:57