1.静态方法加锁:类锁
Synchronized修饰静态方法,实际上是对该类对象加锁,俗称“类锁”
2.非非静态方法加锁:对象锁
Synchronized修饰非静态方法,实际上是对调用该方法的对象加锁,俗称“对象锁”
public class TestSyn {
private static int num = 20;
// 单例模式 静态内部类
public static TestSyn testSyn = new TestSyn();
public synchronized void aVoid() {
for (int i=0;i<10;i++) {
num--;
try {
System.out.println("avoid getNum:" + num);
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public synchronized static void bVoid(){
for (int i=0;i<10;i++) {
num--;
try {
System.out.println("bVoid getNum:" + num);
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
测试类:
public static void main(String[] args) {
Thread thread1 = new Thread(() -> {
TestSyn testSyn = new TestSyn();
testSyn.aVoid();
});
Thread thread2 = new Thread(() -> {
TestSyn.bVoid();
});
thread1.start();
thread2.start();
}
结果
根据执行结果可以得出:静态方法加锁与非静态方法加的锁不是同一个锁
测试类修改成
public static void main(String[] args) {
Thread thread1 = new Thread(() -> {
// TestSyn testSyn = new TestSyn();
TestSyn.testSyn.aVoid();
});
Thread thread2 = new Thread(() -> {
TestSyn.bVoid();
});
thread1.start();
thread2.start();
}
结果互斥:说明这里静态方法,非静态方法使用了相同的锁。
将方法上的加锁机制做下调整:
public static void bVoid(){
synchronized(TestSyn.class){
for (int i=0;i<10;i++) {
num--;
try {
System.out.println("bVoid getNum:" + num);
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
得出的结果互斥:
总结:
1.对象锁钥匙只能有一把才能互斥,才能保证共享变量的唯一性
2.在静态方法上的锁,和 实例方法上的锁,默认不是同样的,如果同步需要制定两把锁一样。
3.关于同一个类的方法上的锁,来自于调用该方法的对象,如果调用该方法的对象是相同的,那么锁必然相同,否则就不相同。
比如 new A().x() 和 new A().x(),对象不同,锁不同,如果A的单例的,就能互斥。
4.静态方法加锁,能和所有其他静态方法加锁的 进行互斥
5.静态方法加锁,和xx.class 锁效果一样,直接属于类的