同步方法与静态同步方法各自的锁对象是谁
同步方法与静态同步方法各自的锁对象是谁
synchronized实现同步的基础:Java中的每一个对象都可以作为锁。
具体表现为以下3种形式。
对于普通同步方法,锁是当前实例对象。
对于静态同步方法,锁是当前类的Class对象。
对于同步方法块,锁是Synchonized括号里配置的对象。
解释:
也就是说如果一个实例对象的非静态同步方法获取锁后,该实例对象的其他非静态同步方法必须等待获取锁的方法释放锁后才能获取锁, 可是别的实例对象的非静态同步方法因为跟该实例对象的非静态同步方法用的是不同的锁, 所以毋须等待该实例对象已获取锁的非静态同步方法释放锁就可以获取他们自己的锁。
所有的静态同步方法用的也是同一把锁——类对象本身, 这两把锁是两个不同的对象,所以静态同步方法与非静态同步方法之间是不会有竞态条件的。 但是一旦一个静态同步方法获取锁后,其他的静态同步方法都必须等待该方法释放锁后才能获取锁,
结论:
普通同步方法,锁是当前实例对象。
不同的实例对象调用非静态同步方法不存在竞态关系
同一个实例对象调用非静态同步方法时存在竞态关系
静态同步方法,锁是当前类的Class对象。
调用静态同步方法和其他静态方法存在竞态关系
与非静态方法不存在竞态关系
演示代码(运行看效果)
public class SyncMethodTest { public static void main(String[] args) { //不同的实例对象,调用同步方法时各自持有自己的锁,不存在竞争关系 SynEntity syn = new SynEntity(); SynEntity synT = new SynEntity(); //静态同步方法获取锁后,因为用的是同一把锁(类对象本身),其他静态同步方法都必须等待该方法释放锁 new Thread(() -> { SynEntity.method1(); }).start(); new Thread(() -> { SynEntity.method2(); }).start(); new Thread(() -> { syn.method3(); }).start(); new Thread(() -> { synT.method3(); }).start(); new Thread(() -> { syn.method4(); }).start(); } }
public class SynEntity { public synchronized static void method1() { System.out.println("静态方法method1执行开始"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("静态方法method1执行结束"); } public synchronized static void method2() { System.out.println("静态方法method2执行开始"); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("静态方法method2执行结束"); } public synchronized void method3() { System.out.println("普通方法method3执行开始"); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("普通方法method3执行结束"); } public synchronized void method4() { System.out.println("普通方法method4执行开始"); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("普通方法method4执行结束"); } }
参考文档地址1: