对象锁和类锁的区别

​ 无论是对象锁还是类锁,我们分析的标准就是我们要获取的资源是否与创建新的对象有关。比如类信息、静态变量的数据无论创建多少个对象都只存在一份,而成员变量这种随着新对象的创建而创建。

类锁就是用在整个类上的锁,对象锁是用在实例上的锁。

对象锁还要分为对谁上锁:

  • 对非静态变量上锁:只在当前线程或者当前对象上会发生阻塞,也就是不同的实例就不会阻塞,因为这些变量不是对类的,而是实例所有的。
  • 对非静态方法上锁:只在当前线程或者当前对象上会发生阻塞
  • 对this本身的实例上锁:只在当前线程或者当前对象上会发生阻塞
  • 对static相关的上锁:他是共享的一个锁,所以不同的对象在不同线程进行获得锁,会因为没有获得到锁产生阻塞。

凡是在堆和方法区的变量做锁获取的资源,都会涉及到这些问题。

类锁:

是放在加载类上,类信息在方法区,整个JVM只有一份,所以他无论在什么时候都是阻塞的。实现方式

  • 在static的方法上加synchronized
  • 在static变量上加synchronized
  • synchronized获取Class对象

测试代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
class ObjectLock{
private Object object = new Object();
private static Object staticObject = new Object();
private static volatile ObjectLock singleton;
// 测试对非静态变量加锁
public void nonStaticVariable() throws InterruptedException {
synchronized(object) {
System.out.println(this);
System.out.println("ObjectLock");
Thread.sleep(1000);
}
}
// 测试对非静态方法加锁
public synchronized void nonStaticMethod() throws InterruptedException {
System.out.println("ObjectLock Method");
Thread.sleep(1000);
}
// 测试对对象加锁
public void nonStaticThis() throws InterruptedException {
synchronized(this) {
System.out.println(this);
System.out.println("ObjectLock This");
Thread.sleep(1000);
}
}
// DCL单例模式
public static ObjectLock getSingleton() throws InterruptedException {
if (singleton == null) {
synchronized (ObjectLock.class) {
if (singleton == null) {
singleton = new ObjectLock();
}
}
}
return singleton;
}
// 测试对静态变量加锁
public void staticVariable() throws InterruptedException {
synchronized(staticObject) {
System.out.println(this);
System.out.println("ObjectLock Static Variable");
Thread.sleep(1000);
}
}
// 测试对静态方法加锁
public synchronized static void staticMethod() throws InterruptedException {
System.out.println("ObjectLock Static Method");
Thread.sleep(1000);
}


public static void main(String[] args) {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
ObjectLock objectLock = null;
try {
objectLock = ObjectLock.getSingleton();
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
objectLock.staticVariable();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
ObjectLock objectLock = null;
try {
objectLock = ObjectLock.getSingleton();
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
objectLock.staticVariable();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
// Thread t1 = new Thread(new Runnable() {
// @Override
// public void run() {
// ObjectLock objectLock = new ObjectLock();
// try {
// objectLock.staticVariable();
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// }
// });
// Thread t2 = new Thread(new Runnable() {
// @Override
// public void run() {
// ObjectLock objectLock = new ObjectLock();
// try {
// objectLock.staticVariable();
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// }
// });
t1.start();
t2.start();
}
}