synchronized的对象锁和类锁的区别

synchronized可以锁对象,代码块,类对象 ,那么他们用起来会有区别吗,这里我们用实际代码来探究下

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
java复制代码package com.example.hxk.thread.synchroized;

public class SyncTest1 {

// synchronized修饰实例方法
public synchronized void test1() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

// synchronized代码块
public void test2() {
synchronized (this) {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

public static void main(String[] args) {
SyncTest1 t1 = new SyncTest1();

new Thread(new Runnable() {
@Override
public void run() {
t1.test1();
}
}, "thread1").start();

new Thread(new Runnable() {
@Override
public void run() {
t1.test2();
}
}, "thread2").start();
}
}

运行结果:

1
2
3
4
5
6
7
8
9
10
java复制代码thread1 : 0
thread1 : 1
thread1 : 2
thread1 : 3
thread1 : 4
thread2 : 0
thread2 : 1
thread2 : 2
thread2 : 3
thread2 : 4

这里thread2会等thread1运行完成才会开始运行,说明thread1和thread2请求的是同一把锁,也就说明了 synchronized代码块锁当前对象和锁实例方法,他们的效果是一样的, 锁的都是当前对象。

然后我们再来看看类锁,修改代码如下

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
java复制代码package com.example.hxk.thread.synchroized;

public class SyncTest1 {

// 修饰静态方法
public static synchronized void test1() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

// 修饰类对象
public void test2() {
synchronized (SyncTest1.class) {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

public static void main(String[] args) {
SyncTest1 t1 = new SyncTest1();

new Thread(new Runnable() {
@Override
public void run() {
SyncTest1.test1();
}
}, "thread1").start();

new Thread(new Runnable() {
@Override
public void run() {
t1.test2();
}
}, "thread2").start();
}
}

运行结果:

1
2
3
4
5
6
7
8
9
10
java复制代码thread1 : 0
thread1 : 1
thread1 : 2
thread1 : 3
thread1 : 4
thread2 : 0
thread2 : 1
thread2 : 2
thread2 : 3
thread2 : 4

这里可以看到thread2也是被thread1阻塞,所以他们持有的是同一把锁,也就说明synchronized修饰静态方法和锁类对象,他们的效果是一样的。
接下来我们同时用类锁和对象锁试试,代码如下

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
java复制代码package com.example.hxk.thread.synchroized;

public class SyncTest1 {

// 修饰静态方法
public static synchronized void test1() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

// 修饰类对象
public synchronized void test2() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

public static void main(String[] args) {
SyncTest1 t1 = new SyncTest1();

new Thread(new Runnable() {
@Override
public void run() {
SyncTest1.test1();
}
}, "thread1").start();

new Thread(new Runnable() {
@Override
public void run() {
t1.test2();
}
}, "thread2").start();
}
}

运行结果:

1
2
3
4
5
6
7
8
9
10
java复制代码thread1 : 0
thread2 : 0
thread1 : 1
thread2 : 1
thread2 : 2
thread1 : 2
thread2 : 3
thread1 : 3
thread2 : 4
thread1 : 4

运行结果是交替进行的,说明对象锁和类锁锁的不是同一个锁,他们是两个锁,互不影响

总结:

1,synchronized修饰在实例方法上和synchronized(this){} 同步代码块效果是一样的

2,synchronized修饰在静态方法上和 synchronized (SyncTest1.class) {} 同步代码块效果是一样的

3,synchronized修饰在实例方法表示锁的是当前对象,修饰静态方法表示锁的是类对象(一个类在jvm中只有一个class对象)

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%