On the Java lock

Whenever Java interview, "lock" is bound to be mentioned stuff. So, in the interview, we talk about "lock" will talk about what to do, and whether you Tell me to "lock" enough to understand?

This article aims to analyze the underlying principles of the lock, and lock application scenarios.

一、Synchronized

1, a face questions

Two synchronization methods writer and reader access to the same object in the object are A, B two threads, will produce mutually exclusive?

      
      
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
      
      
class {
int a = 0;
public synchronized void writer(){
sleep( 10);
a++;
}
public synchronized void reader(){
int i = a;
}
public static void main(String[] args) {
Test test = new Test();
new Thread(() -> {
test.writer();
}).start();
sleep( 1);
new Thread(() -> {
test.reader();
}).start();
}
}

答案:会。因为synchronized修饰的是方法,锁是对象锁,默认当前的对象作为锁的对象。只有当A释放锁之后,B才会获得对象的锁。

(1)如果是换成是不同对象呢?

不会互斥,因为锁的是对象,而不是方法

(2)如果writer、reader方法加上static修饰,两个线程中,类直接调用两个方法呢?

会互斥,因为锁的是Class对象。

(3)如果writer方法用static修饰,reader方法不用呢?

不会互斥。因为一个是对象锁,一个是Class对象锁,锁的类型不同。

synchronized修饰位置与锁的关系

  • 同步方法 —— 对象锁,当前实例对象
  • 静态同步方法 —— 类对象锁,当前对象的Class对象
  • 同步方法块 —— 对象锁,synchonized括号里配置的对象

二、锁的底层实现

思考几个问题

  1. 对象锁、Class对象锁时如何实现的
  2. 为什么要这么设计,只设计一个对象锁或Class对象锁,有什么不好?

1、反编译

      
      
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
      
      
class {
static int a = 0;
public synchronized void writer() {
System.out.println( "writer方法开始调用");
a++;
waitNs( 20);
System.out.println( "writer方法调用结束");
}
public static synchronized void reader() {
System.out.println( "reader方法开始调用");
int i = a;
System.out.println( "reader方法调用结束");
}
public void writer2() {
synchronized ( this) {
a--;
}
}
}

使用javacjavap -verbose命令,反编译上述代码

      
      
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
111
112
113
114
115
116
117
      
      
...
{
static int a;
descriptor: I
flags: ACC_STATIC
public com.fonxian.entity.LockDemo();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 6: 0
//同步方法
public synchronized void writer();
descriptor: ()V
flags: ACC_PUBLIC, ACC_SYNCHRONIZED
Code:
stack=2, locals=1, args_size=1
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #3 // String writer方法开始调用
5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: getstatic #5 // Field a:I
11: iconst_1
12: iadd
13: putstatic #5 // Field a:I
16: bipush 20
18: invokestatic #6 // Method waitNs:(I)V
21: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
24: ldc #7 // String writer方法调用结束
26: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
29: return
LineNumberTable:
line 11: 0
line 12: 8
line 13: 16
line 14: 21
line 15: 29
//静态同步方法
public static synchronized void reader();
descriptor: ()V
flags: ACC_PUBLIC, ACC_STATIC, ACC_SYNCHRONIZED
Code:
stack=2, locals=1, args_size=0
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #8 // String reader方法开始调用
5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: getstatic #5 // Field a:I
11: istore_0
12: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
15: ldc #9 // String reader方法调用结束
17: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
20: return
LineNumberTable:
line 18: 0
line 19: 8
line 20: 12
line 21: 20
//同步代码块
public void writer2();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=2, locals=3, args_size=1
0: aload_0
1: dup
2: astore_1
3: monitorenter
4: getstatic #5 // Field a:I
7: iconst_1
8: isub
9: putstatic #5 // Field a:I
12: aload_1
13: monitorexit
14: goto 22
17: astore_2
18: aload_1
19: monitorexit
20: aload_2
21: athrow
22: return
Exception table:
from to target type
4 14 17 any
17 20 17 any
LineNumberTable:
line 25: 0
line 26: 4
line 27: 12
line 28: 22
StackMapTable: number_of_entries = 2
frame_type = 255 /* full_frame */
offset_delta = 17
locals = [ class com/fonxian/entity/LockDemo, class java/lang/Object ]
stack = [ class java/lang/Throwable ]
frame_type = 250 /* chop */
offset_delta = 4
static {};
descriptor: ()V
flags: ACC_STATIC
Code:
stack=1, locals=0, args_size=0
0: iconst_0
1: putstatic #5 // Field a:I
4: return
LineNumberTable:
line 8: 0
}
SourceFile: "LockDemo.java"

同步代码块:使用monitorenter和monitorexit指令实现,通过监听器对象去获得锁释放锁

同步方法、静态同步方法:使用修饰符ACC_SYNCHRONIZED实现。

三、锁的形式

Before JDK1.6, synchronized only the traditional locking mechanism.
JDK1.6 introduced two new types of locks: biased locking lock and lightweight. The purpose is to solve the introduction, there is no multi-threaded competition or no competition cases, performance problems caused by traditional lock.

Four states lock: no lock status, tend to lock status, lock status lightweight, heavyweight lock status. Lock can be upgraded, not downgraded.

1, the object head

To unlock the mechanism, we must first understand the object header.

Java object head of Mark Word default storage object HashCode, age and generational lock flag.

Storing Java object header structure is as follows :

Lock status 25bit 4bit 1bit whether it is biased locking 2bit lock flag
Lock-free status hashCode object Generational age of the subject 0 01

Mark Word of state changes :

Lock status 30bit 2bit
Lightweight lock Pointing the stack pointer record lock Lock flag 00
Heavyweight lock A pointer pointing mutex Lock flag 10
Lock status 23bit 3bit 3bit 1bit 2bit
Biased locking Thread ID Epoch Object generational Age 1 01

2, biased locking

Because in most cases, there is no lock multithreaded competition, and the total obtained by the same thread several times. In order to lower the cost to acquire a lock is introduced.

3, lightweight lock

Reference Documents

1, JDK8 HotSpot Virtual Machine Source

Original: Big Box  On Java lock


Guess you like

Origin www.cnblogs.com/chinatrump/p/11614930.html