同步方法与同步块的区别

221 阅读4分钟

java使用synchronized同步,分为四种情况:




  • 实例方法同步
  • 实例方法中同步块
  • 静态方法同步
  • 静态方法中同步块



我们从两个方面来说他们的不同,一个是同步方法和同步块的区别,一个是静态和非静态的区别。

同步方法就是在方法前加关键字synchronized,然后被同步的方法一次只能有一个线程进入,其他线程等待。而同步方法则是在方法内部使用大括号使得一个代码块得到同步。同步块会有一个同步的”目标“,使得同步块更加灵活一些(同步块可以通过”目标“决定需要锁定的对象)。一般情况下,如果此”目标“为this,那么同步方法和同步块没有太大的区别。


另外,通过反编译可以看出,同步块比同步方法多了两个指令。因此同步方法是比同步块要快一些。


非静态和静态的区别主要在于(以同步方法为例): 非静态的同步方法是锁定类的实例的,而静态的同步方法是锁定类的;

也就是说,对于非静态的同步方法,在同一时刻,一个类的一个实例中,只有一个线程能进入同步的方法。但是对于多个实例,每一个实例的一个线程都可以进入同一同步的方法。

Demo1:一个实例的多个线程,一次只能有一个线程进入非静态同步的方法。


[Java]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
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
package SynchronizedTest;
/**
* Created by carrot on 16/8/31.
*/
public class SyncFunc {
public synchronized void func1() {
System.out.println(Thread.currentThread().getName() + " is running");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " is stop");
}
public static void main(String[] args) {
NewThread newThread1 = new NewThread();
NewThread newThread2 = new NewThread();
NewThread newThread3 = new NewThread();
newThread1.start();
newThread2.start();
newThread3.start();
}
}
class NewThread extends Thread {
static SyncFunc syncFunc = new SyncFunc();
@Override
public void run() {
syncFunc.func1();
}
}


结果:

[Java]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
Thread-0 is running
Thread-0 is stop
Thread-2 is running
Thread-2 is stop
Thread-1 is running
Thread-1 is stop


从结果可见,每次只能有一个线程进入非静态同步的方法。


Demo2:多个实例的线程能同时进入非静态同步的方法。


结果:

Thread-0 is running

[Java]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
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
package SynchronizedTest;[/p]
/**
* Created by carrot on 16/8/31.
*/
public class SyncFunc {
public synchronized void func1() {
System.out.println(Thread.currentThread().getName() + " is running");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " is stop");
}
public static void main(String[] args) {
NewThread newThread1 = new NewThread();
NewThread newThread2 = new NewThread();
NewThread newThread3 = new NewThread();
newThread1.start();
newThread2.start();
newThread3.start();
}
}
class NewThread extends Thread {
SyncFunc syncFunc = new SyncFunc();
@Override
public void run() {
syncFunc.func1();
}
}

结果:

[Java]
纯文本查看
复制代码
1
2
3
4
5
6
7
8
9
Thread-1 is running
Thread-2 is running
Thread-0 is stop
Thread-2 is stop
Thread-1 is stop


从结果可以看出,多个实例的线程同时进入了同步的非静态方法。


Demo3:多个实例的线程进入静态的同步方法。

[Java]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
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
package SynchronizedTest;
/**
* Created by carrot on 16/8/31.
*/
public class SyncFunc {
public static synchronized void func1() {
System.out.println(Thread.currentThread().getName() + " is running");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " is stop");
}
public static void main(String[] args) {
NewThread newThread1 = new NewThread();
NewThread newThread2 = new NewThread();
NewThread newThread3 = new NewThread();
newThread1.start();
newThread2.start();
newThread3.start();
}
}
class NewThread extends Thread {
SyncFunc syncFunc = new SyncFunc();
@Override
public void run() {
syncFunc.func1();
}
}

结果:

[Java]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
Thread-0 is running
Thread-0 is stop
Thread-2 is running
Thread-2 is stop
Thread-1 is running
Thread-1 is stop


从结果可以看出,对于同一个对象的多个实例,在进入静态的同步方法时,一次只能有一个类实例进

---------------------

作者:SilenceCarrot

来源:CSDN

原文:https://blog.csdn.net/SilenceCarrot/article/details/52415704


版权声明:本文为博主原创文章,转载请附上博文链接