java-doc-synchronized

synchronized

在Java实现同步可以通过给方法添加关键字synchronized修饰要同步的对象,也可以通过synchronized()方法来执行需要同步的方法,但是单独使用synchronized经常会导致不合理的现象,因此通常和wait()和notify()搭配使用。

synchronized关键字,不仅实现同步,JMM中规定,synchronized要保证可见性(不能够被缓存)

相比Lock,Synchronized使用简单,语义清晰,哪里需要点哪里。由JVM提供, 提供了多种优化方案(锁粗化、锁消除、偏向锁、轻量级锁)。锁的释放由虚拟机来完成,不用人工干预,也降低了死锁的可能性。但是不能实现公平锁、中断锁等高级功能。

synchronized与this

synchronized修饰对象自己的时候,把对象实例用作要锁的对象,等同于对象的方法被synchronized修饰,各个对象实例对方法的调用不会造成影响。

1
2
3
4
5
6
7
8
9
10
11
class Sync{
public synchronized void S1(){
// ...
}

public void S2(){
synchronized (this){
// ...
}
}
}

synchronized与class

synchronized修饰对象的class对象时,把对象的class作为全局锁的对象,等同于对象的静态方法synchronized修饰,各个对象实例对方法的调用会相互影响。

1
2
3
4
5
6
7
8
9
10
11
class Sync2{
public static synchronized void S1(){
// ...
}

public void S2(){
synchronized (Sync2.class){
// ...
}
}
}

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
49
50
51
52
53
54
55
56
57
58
59
60
class Callme
{
void Call(String msg)
{
System.out.print("[" + msg);

try {
Thread.sleep(1000);
} catch(InterruptedException e) {
System.out.println("Interrupted");
}

System.out.println("]");
}
}

class Caller implements Runnable
{
String msg;
Callme target;
Thread t;

public Caller(Callme targ, String s)
{
this.msg = s;
this.target = targ;
t = new Thread(this);
t.start();
}

public void run()
{
this.target.Call(msg);
}
}

public class LearnThreadSyn
{
public static void main(String args[])
{
Callme target = new Callme();
Caller obj1 = new Caller(target, "Hello");
Caller obj2 = new Caller(target, "Synchronized");
Caller obj3 = new Caller(target, "World");

try {
obj1.t.join();
obj2.t.join();
obj3.t.join();
} catch (InterruptedException e) {
System.out.println("Interrupted");
}

// 输出
// [Hello[World[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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package helloworld;

class Callme
{
// 方法加synchronized
synchronized void Call(String msg)
{
System.out.print("[" + msg);

try {
Thread.sleep(1000);
} catch(InterruptedException e) {
System.out.println("Interrupted");
}

System.out.println("]");
}
}

class Caller implements Runnable
{
String msg;
Callme target;
Thread t;

public Caller(Callme targ, String s)
{
this.msg = s;
this.target = targ;
t = new Thread(this);
t.start();
}

public void run()
{
this.target.Call(msg);
}
}

public class LearnThreadSyn
{
public static void main(String args[])
{
Callme target = new Callme();
Caller obj1 = new Caller(target, "Hello");
Caller obj2 = new Caller(target, "Synchronized");
Caller obj3 = new Caller(target, "World");

try {
obj1.t.join();
obj2.t.join();
obj3.t.join();
} catch (InterruptedException e) {
System.out.println("Interrupted");
}

// 输出
// [Hello]
// [World]
// [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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
package helloworld;

class Callme
{
void Call(String msg)
{
System.out.print("[" + msg);

try {
Thread.sleep(1000);
} catch(InterruptedException e) {
System.out.println("Interrupted");
}

System.out.println("]");
}
}

class Caller implements Runnable
{
String msg;
Callme target;
Thread t;

public Caller(Callme targ, String s)
{
this.msg = s;
this.target = targ;
t = new Thread(this);
t.start();
}

public void run()
{
// synchronized同步对象
synchronized(this.target) {
this.target.Call(msg);
}
}
}

public class LearnThreadSyn
{
public static void main(String args[])
{
Callme target = new Callme();
Caller obj1 = new Caller(target, "Hello");
Caller obj2 = new Caller(target, "Synchronized");
Caller obj3 = new Caller(target, "World");

try {
obj1.t.join();
obj2.t.join();
obj3.t.join();
} catch (InterruptedException e) {
System.out.println("Interrupted");
}

// 输出
// [Hello]
// [World]
// [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
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
class Q
{
int n;

synchronized int get()
{
System.out.println("Got :" + n);
return n;
}

synchronized void put(int n)
{
this.n = n;
System.out.println("Put :" + n);
}
}

class Producer implements Runnable
{
Q q;

Producer(Q q)
{
this.q =q;
new Thread(this, "Producer").start();
}

public void run()
{
int i = 0;

while(true) {
q.put(i++);
}
}
}

class Consumer implements Runnable
{
Q q;

Consumer(Q q)
{
this.q = q;
new Thread(this, "Consumer").start();
}

public void run()
{
while(true) {
q.get();
}
}
}

public class LearnThreadComm
{
public static void main(String args[])
{
Q q = new Q();
new Producer(q);
new Consumer(q);

System.out.println("Stop");

// 可能的结果
// Put :1
// Got :1
// Got :1
// Got :1
// Got :1
// Put :2
// Put :3
// Put :4
// ...
}
}