一、Synchronized修饰实例方法,实际上是对调用该方法的对象加锁,俗称“对象锁”
情况一:同一个对象在两个线程中分别访问该对象的两个同步实例方法
结果:会产生互斥
原因:因为锁针对的是对象,当对象调用一个synchronized方法时,其他同步方法需要等待其执行结束并释放锁之后才能执行
例子:
synchronized修饰实例方法情况一
运行结果:(可能出现的情况)
1、Thread-0
得到锁-->10s之后-->Thread-0
释放锁-->Thread-1
得到锁-->Thread-1
释放锁
2、Thread-1
得到锁-->Thread-1
释放锁-->Thread-0
得到锁-->10s之后-->Thread-0
释放锁
情况二:不同对象在两个线程中分别调用同一个同步实例方法
结果:不会互斥
原因:因为是两个对象,锁针对的是对象,并不是方法,所以可以并发执行,不会互斥。
例子:
synchronized修饰实例方法情况二
运行结果:(可能出现的情况)
1、Thread-0
得到锁-->Thread-1
得到锁-->Thread-1
释放锁-->10s之后-->Thread-0释放锁
2、Thread-1 得到锁-->Thread-1
释放锁-->Thread-0
得到锁-->10s之后-->Thread-0
释放锁
3、Thread-0
得到锁-->Thread-1
得到锁-->Thread-1
释放锁-->10s之后-->Thread-0
释放锁
4、Thread-1
得到锁-->Thread-0
得到锁-->Thread-1
释放锁-->10s之后-->Thread-0
释放锁
二、Synchronized修饰静态方法,实际上是对该类对象,俗称“类锁”
情况一:用类直接在两个线程中调用两个不同的同步静态方法
结果:会产生互斥
原因:因为对静态方法加锁,实际上是对类加锁,类只有一个。因此当一个同步静态方法被访问时,该类已处于被锁状态。此时其他同步静态方法不能被访问(未用Synchronized修饰的静态方法仍可以访问)
例子:
synchronized修饰静态方法情况一
运行结果:(可能出现的情况)
1、Thread-1 得到锁-->Thread-1
释放锁-->Thread-0
得到锁-->10s之后-->Thread-0 释放锁
2、Thread-0
得到锁-->10s之后-->Thread-0
释放锁-->Thread-1 得到锁-->Thread-1释放锁
情况二:用一个类的静态对象在两个线程中调用同步静态方法
结果:会产生互斥
原因:与同一个对象在两个线程中分别访问该对象的两个同步实例方法情况相同。本质上还是对类的加锁
例子:
synchronized修饰静态方法情况二
运行结果:(可能出现的情况)
1、Thread-0 得到锁-->10s之后-->Thread-0
释放锁-->Thread-1 得到锁-->Thread-1 释放锁
2、Thread-1
得到锁-->Thread-1 释放锁-->Thread-0
得到锁-->10s之后-->Thread-0 释放锁
情况三:一个对象在两个线程中分别调用一个同步静态方法和一个同步实例方法
结果:不会产生互斥
原因:虽然是一个对象调用,但是两个方法的锁类型不同,调用静态方法实际上是对类对象在调用,而调用实例方法实际上是对实例对象在调用。因为这两个方法并不是一个对象锁,因为不会互斥,会并发执行
例子:
synchronized修饰静态方法情况三
运行结果:(可能出现的情况)
1、Thread-0 得到锁-->Thread-1
得到锁-->10s之后-->Thread-1
释放锁-->Thread-0 释放锁
2、Thread-0 得到锁-->Thread-1
得到锁-->10s之后-->Thread-0
释放锁-->Thread-1 释放锁
3、Thread-1 得到锁-->Thread-0
得到锁-->10s之后-->Thread-0
释放锁-->Thread-1
释放锁
3、Thread-1 得到锁-->Thread-0
得到锁-->10s之后-->Thread-1
释放锁-->Thread-0释放锁
三、结论
1、静态方法的锁和实例方法的锁,默认是不同的对象锁
2、静态方法加锁,能和该类中所有用synchronized修饰静态方法的相互互斥,和未用synchronized修饰的静态方法不互斥
3、静态方法锁实际是对类对象加锁,实例方法加锁实际是对实例对象加锁
四、参考文章