java并發synchronized 鎖的膨脹過程(鎖的升級過程)深入剖析(2)

接下來我們分析兩個批量偏向撤銷的相關案例(禁止偏向鎖延遲的情況下:-XX:+UseBiasedLocking -XX:BiasedLockingStartupDelay=0):

案例一:

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

public?class?TestDemo {

}

??

public?class?DemoExample6 {

????public?static?void?main(String[] args)?throws?InterruptedException {

????????test2();

????}

???

????/**

?????* 證明偏量偏向撤銷

?????* @throws InterruptedException

?????*/

????public??static??void?test2()?throws?InterruptedException {

????????List<TestDemo> list =?new?ArrayList<TestDemo>();

????????for?(int?i =?0; i <?100; i++) {

????????????list.add(new?TestDemo());

????????}

????????Thread t1 =?new?Thread(()->{

????????????System.out.println("加鎖前 get(0) 應該是無鎖可偏向 "+ClassLayout.parseInstance(list.get(0)).toPrintable());

????????????for?(TestDemo a:list? ) {

????????????????synchronized?(a){

????????????????????System.out.print("加鎖 >");

????????????????}

????????????}

????????????System.out.println();

????????????System.out.println("加鎖后 get(0) 應該是偏向鎖"+ClassLayout.parseInstance(list.get(0)).toPrintable());

????????????try?{

????????????????TimeUnit.SECONDS.sleep(1000);//這里不讓線程死,防止線程ID復用

????????????}?catch?(InterruptedException e) {

????????????????e.printStackTrace();

????????????}

????????});

????????t1.start();

????????TimeUnit.SECONDS.sleep(5);

????????Thread t2 =?new?Thread(()->{

????????????for?(int?i =?0; i <?100; i++) {

????????????????TestDemo a = list.get(i);

????????????????synchronized?(a){

????????????????????System.out.println(Thread.currentThread().getId()+"加鎖 >");

????????????????}

????????????????try?{

????????????????????TimeUnit.MILLISECONDS.sleep(100);

????????????????}?catch?(InterruptedException e) {

????????????????????e.printStackTrace();

????????????????}

????????????????if?(i==9){//這里剛好是第19個上鎖的(同樣是第19個偏向鎖升級的)

????????????????????System.out.println();

????????????????????System.out.println("加鎖后 get(9) 應該是無鎖(輕量級鎖釋放) "+ClassLayout.parseInstance(list.get(i)).toPrintable());

????????????????}

????????????????if?(i==10){//這里剛好是第21個上鎖的

????????????????????System.out.println();

????????????????????System.out.println("加鎖后 get(10) 應該是偏向鎖 偏向t2 "+ClassLayout.parseInstance(list.get(i)).toPrintable());

????????????????}

????????????????if?(i==50){//50開始升級為輕量級鎖(同樣是第21個偏向鎖升級的)

????????????????????System.out.println();

????????????????????System.out.println("加鎖后 get(50) 無鎖(輕量級鎖釋放) "+ClassLayout.parseInstance(list.get(i)).toPrintable());

????????????????}

????????????????if?(i==59){//60(同樣是第39個偏向鎖升級的)

????????????????????System.out.println();

????????????????????System.out.println("加鎖后 get(59) 無鎖(輕量級鎖釋放) "+ClassLayout.parseInstance(list.get(i)).toPrintable());

????????????????}

????????????????if?(i==69){//69(同樣是第59個偏向鎖升級的)

????????????????????System.out.println();

????????????????????System.out.println("加鎖后 get(69) 無鎖(輕量級鎖釋放) "+ClassLayout.parseInstance(list.get(i)).toPrintable());

????????????????????TestDemo a1 =?new?TestDemo();

????????????????????synchronized?(a1){

????????????????????????System.out.println("偏向撤銷發生后的該類新建的對象都不會再偏向任何線程 "+ClassLayout.parseInstance(a1).toPrintable());

????????????????????}

????????????????}

????????????}

????????});

???

????????Thread t3 =?new?Thread(()->{

????????????for?(int?i =?99; i >=?0; i--) {

????????????????TestDemo a = list.get(i);

????????????????synchronized?(a){

????????????????????System.out.println(Thread.currentThread().getId()+"加鎖 >");

????????????????}

????????????????try?{

????????????????????TimeUnit.MILLISECONDS.sleep(100);

????????????????}?catch?(InterruptedException e) {

????????????????????e.printStackTrace();

????????????????}

????????????????/**

?????????????????* 重點:重偏向撤銷

?????????????????*/

????????????????if?(i==40){//40升級為輕量級鎖(同樣是第40個偏向鎖升級的,這時候發生偏向撤銷)

????????????????????System.out.println();

????????????????????System.out.println("加鎖后 get("+i+") 應該是無鎖(輕量級鎖釋放) "+ClassLayout.parseInstance(list.get(0)).toPrintable());

????????????????????TestDemo a1 =?new?TestDemo();

????????????????????synchronized?(a1){

????????????????????????System.out.println("偏向撤銷發生后的該類新建的對象都不會再偏向任何線程 "+ClassLayout.parseInstance(a1).toPrintable());

????????????????????}

????????????????}

????????????????if?(i==30){//39升級為輕量級鎖(同樣是第42個偏向鎖升級的)

????????????????????System.out.println();

????????????????????System.out.println("加鎖后 get("+i+") 應該是無鎖(輕量級鎖釋放) "+ClassLayout.parseInstance(list.get(0)).toPrintable());

????????????????????TestDemo a1 =?new?TestDemo();

????????????????????synchronized?(a1){

????????????????????????System.out.println("偏向撤銷發生后的該類新建的對象都不會再偏向任何線程 "+ClassLayout.parseInstance(a1).toPrintable());

????????????????????}

????????????????}

????????????}

????????});

????????t2.start();

????????TimeUnit.MILLISECONDS.sleep(50);

????????t3.start();

????}

}  

?

運行結果(截取部分):

加鎖前 get(0) 應該是無鎖可偏向?com.boke.TestDemo object internals:

OFFSET??SIZE???TYPE DESCRIPTION???????????????????????????????VALUE

??????0?????4????????(object header)???????????????????????????05 00 00 00 (00000101?00000000 00000000 00000000) (5)

??????4?????4????????(object header)???????????????????????????00 00 00 00 (00000000 00000000 00000000 00000000) (0)

??????8?????4????????(object header)???????????????????????????43 c1 00 f8 (01000011 11000001 00000000 11111000) (-134168253)

?????12?????4????????(loss due to the next object alignment)

Instance size: 16 bytes

Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

?

?

加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >加鎖 >

?

加鎖后 get(0) 應該是偏向鎖com.boke.TestDemo object internals:

OFFSET??SIZE???TYPE DESCRIPTION???????????????????????????????VALUE

??????0?????4????????(object header)???????????????????????????05 e0 84 08 (00000101?11100000 10000100 00001000) (142925829)

??????4?????4????????(object header)???????????????????????????b1 7f 00 00 (10110001 01111111 00000000 00000000) (32689)

??????8?????4????????(object header)???????????????????????????43 c1 00 f8 (01000011 11000001 00000000 11111000) (-134168253)

?????12?????4????????(loss due to the next object alignment)

Instance size: 16 bytes

Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

?

加鎖后 get(9) 應該是無鎖(輕量級鎖釋放)?com.boke.TestDemo object internals:

OFFSET??SIZE???TYPE DESCRIPTION???????????????????????????????VALUE

??????0?????4????????(object header)???????????????????????????01 00 00 00 (00000001?00000000 00000000 00000000) (1)

??????4?????4????????(object header)???????????????????????????00 00 00 00 (00000000 00000000 00000000 00000000) (0)

??????8?????4????????(object header)???????????????????????????43 c1 00 f8 (01000011 11000001 00000000 11111000) (-134168253)

?????12?????4????????(loss due to the next object alignment)

Instance size: 16 bytes

Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

?

?

15加鎖 >

?

?

加鎖后 get(90) 應該是偏向鎖 偏向t3com.boke.TestDemo object internals:

OFFSET??SIZE???TYPE DESCRIPTION???????????????????????????????VALUE

??????0?????4????????(object header)???????????????????????????05 89 01 0c (00000101?10001001 00000001 00001100) (201427205)

??????4?????4????????(object header)???????????????????????????b1 7f 00 00 (10110001 01111111 00000000 00000000) (32689)

??????8?????4????????(object header)???????????????????????????43 c1 00 f8 (01000011 11000001 00000000 11111000) (-134168253)

?????12?????4????????(loss due to the next object alignment)

Instance size: 16 bytes

Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

?

加鎖后 get(10) 應該是偏向鎖 偏向t2?com.boke.TestDemo object internals:

OFFSET??SIZE???TYPE DESCRIPTION???????????????????????????????VALUE

??????0?????4????????(object header)???????????????????????????05 b1 0a 08 (00000101?10110001 00001010 00001000) (134918405)

??????4?????4????????(object header)???????????????????????????b1 7f 00 00 (10110001 01111111 00000000 00000000) (32689)

??????8?????4????????(object header)???????????????????????????43 c1 00 f8 (01000011 11000001 00000000 11111000) (-134168253)

?????12?????4????????(loss due to the next object alignment)

Instance size: 16 bytes

Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

?

?

15加鎖 >

?

?

加鎖后 get(89) 應該是無鎖(輕量級鎖釋放)?com.boke.TestDemo object internals:

OFFSET??SIZE???TYPE DESCRIPTION???????????????????????????????VALUE

??????0?????4????????(object header)???????????????????????????01 00 00 00 (00000001?00000000 00000000 00000000) (1)

??????4?????4????????(object header)???????????????????????????00 00 00 00 (00000000 00000000 00000000 00000000) (0)

??????8?????4????????(object header)???????????????????????????43 c1 00 f8 (01000011 11000001 00000000 11111000) (-134168253)

?????12?????4????????(loss due to the next object alignment)

Instance size: 16 bytes

Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

?

加鎖后 get(50) 無鎖(輕量級鎖釋放)?com.boke.TestDemo object internals:

OFFSET??SIZE???TYPE DESCRIPTION???????????????????????????????VALUE

??????0?????4????????(object header)???????????????????????????01 00 00 00 (00000001?00000000 00000000 00000000) (1)

??????4?????4????????(object header)???????????????????????????00 00 00 00 (00000000 00000000 00000000 00000000) (0)

??????8?????4????????(object header)???????????????????????????43 c1 00 f8 (01000011 11000001 00000000 11111000) (-134168253)

?????12?????4????????(loss due to the next object alignment)

Instance size: 16 bytes

Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

?

15加鎖 >

??

加鎖后 get(49) 應該是無鎖(輕量級鎖釋放)?com.boke.TestDemo object internals:

OFFSET??SIZE???TYPE DESCRIPTION???????????????????????????????VALUE

??????0?????4????????(object header)???????????????????????????01 00 00 00 (00000001?00000000 00000000 00000000) (1)

??????4?????4????????(object header)???????????????????????????00 00 00 00 (00000000 00000000 00000000 00000000) (0)

??????8?????4????????(object header)???????????????????????????43 c1 00 f8 (01000011 11000001 00000000 11111000) (-134168253)

?????12?????4????????(loss due to the next object alignment)

Instance size: 16 bytes

Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

?

加鎖后 get(59) 無鎖(輕量級鎖釋放)?com.boke.TestDemo object internals:

OFFSET??SIZE???TYPE DESCRIPTION???????????????????????????????VALUE

??????0?????4????????(object header)???????????????????????????01 00 00 00 (00000001?00000000 00000000 00000000) (1)

??????4?????4????????(object header)???????????????????????????00 00 00 00 (00000000 00000000 00000000 00000000) (0)

??????8?????4????????(object header)???????????????????????????43 c1 00 f8 (01000011 11000001 00000000 11111000) (-134168253)

?????12?????4????????(loss due to the next object alignment)

Instance size: 16 bytes

Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

??

15加鎖 >?

?

加鎖后 get(40) 應該是無鎖(輕量級鎖釋放)?com.boke.TestDemo object internals:

OFFSET??SIZE???TYPE DESCRIPTION???????????????????????????????VALUE

??????0?????4????????(object header)???????????????????????????01 00 00 00 (00000001?00000000 00000000 00000000) (1)

??????4?????4????????(object header)???????????????????????????00 00 00 00 (00000000 00000000 00000000 00000000) (0)

??????8?????4????????(object header)???????????????????????????43 c1 00 f8 (01000011 11000001 00000000 11111000) (-134168253)

?????12?????4????????(loss due to the next object alignment)

Instance size: 16 bytes

Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

??

偏向撤銷發生后的該類新建的對象都不會再偏向任何線程?com.boke.TestDemo object internals:

OFFSET??SIZE???TYPE DESCRIPTION???????????????????????????????VALUE

??????0?????4????????(object header)???????????????????????????48 18 a6 09 (01001000?00011000 10100110 00001001) (161880136)

??????4?????4????????(object header)???????????????????????????00 70 00 00 (00000000 01110000 00000000 00000000) (28672)

??????8?????4????????(object header)???????????????????????????43 c1 00 f8 (01000011 11000001 00000000 11111000) (-134168253)

?????12?????4????????(loss due to the next object alignment)

Instance size: 16 bytes

Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

?

加鎖后 get(69) 無鎖(輕量級鎖釋放)?com.boke.TestDemo object internals:

OFFSET??SIZE???TYPE DESCRIPTION???????????????????????????????VALUE

??????0?????4????????(object header)???????????????????????????01 00 00 00 (00000001?00000000 00000000 00000000) (1)

??????4?????4????????(object header)???????????????????????????00 00 00 00 (00000000 00000000 00000000 00000000) (0)

??????8?????4????????(object header)???????????????????????????43 c1 00 f8 (01000011 11000001 00000000 11111000) (-134168253)

?????12?????4????????(loss due to the next object alignment)

Instance size: 16 bytes

Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

??

偏向撤銷發生后的該類新建的對象都不會再偏向任何線程?com.boke.TestDemo object internals:

OFFSET??SIZE???TYPE DESCRIPTION???????????????????????????????VALUE

??????0?????4????????(object header)???????????????????????????50 e8 95 09 (01010000?11101000 10010101 00001001) (160819280)

??????4?????4????????(object header)???????????????????????????00 70 00 00 (00000000 01110000 00000000 00000000) (28672)

??????8?????4????????(object header)???????????????????????????43 c1 00 f8 (01000011 11000001 00000000 11111000) (-134168253)

?????12?????4????????(loss due to the next object alignment)

Instance size: 16 bytes

Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

??

15加鎖 >

?

加鎖后 get(30) 應該是無鎖(輕量級鎖釋放)?com.boke.TestDemo object internals:

OFFSET??SIZE???TYPE DESCRIPTION???????????????????????????????VALUE

??????0?????4????????(object header)???????????????????????????01 00 00 00 (00000001?00000000 00000000 00000000) (1)

??????4?????4????????(object header)???????????????????????????00 00 00 00 (00000000 00000000 00000000 00000000) (0)

??????8?????4????????(object header)???????????????????????????43 c1 00 f8 (01000011 11000001 00000000 11111000) (-134168253)

?????12?????4????????(loss due to the next object alignment)

Instance size: 16 bytes

Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

??

偏向撤銷發生后的該類新建的對象都不會再偏向任何線程?com.boke.TestDemo object internals:

OFFSET??SIZE???TYPE DESCRIPTION???????????????????????????????VALUE

??????0?????4????????(object header)???????????????????????????48 18 a6 09 (01001000?00011000 10100110 00001001) (161880136)

??????4?????4????????(object header)???????????????????????????00 70 00 00 (00000000 01110000 00000000 00000000) (28672)

??????8?????4????????(object header)???????????????????????????43 c1 00 f8 (01000011 11000001 00000000 11111000) (-134168253)

?????12?????4????????(loss due to the next object alignment)

Instance size: 16 bytes

Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

?

案例二:

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

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

public?class?TestDemo {

}

public?class?DemoExample8 {

????public?static?void?main(String[] args)?throws?Exception {

????????List<TestDemo> list =?new?ArrayList<>();

????????List<TestDemo> list2 =?new?ArrayList<>();

????????List<TestDemo> list3 =?new?ArrayList<>();

????????for?(int?i =?0; i <?100; i++) {

????????????list.add(new?TestDemo());

????????????list2.add(new?TestDemo());

????????????list3.add(new?TestDemo());

????????}

????????//偏向鎖

????????System.out.println("初始狀態"?+?10?+ ClassLayout.parseClass(TestDemo.class).toPrintable());

???

????????Thread t1 =?new?Thread() {

????????????String name =?"1";

????????????public?void?run() {

????????????????System.out.printf(name);

????????????????for?(TestDemo a : list) {

????????????????????synchronized?(a) {

????????????????????????if?(a == list.get(10)) {

????????????????????????????//偏向鎖

????????????????????????????System.out.println("t1 預期是偏向鎖"?+?10?+ ClassLayout.parseInstance(a).toPrintable());

????????????????????????}

????????????????????}

????????????????}

????????????????try?{

????????????????????Thread.sleep(100000);

????????????????}?catch?(InterruptedException e) {

????????????????????e.printStackTrace();

????????????????}

????????????}

????????};

????????t1.start();

????????Thread.sleep(5000);

????????//偏向鎖

????????System.out.println("main 預期是偏向鎖"?+?10?+ ClassLayout.parseInstance(list.get(10)).toPrintable());

????????Thread t2 =?new?Thread() {

????????????String name =?"2";

????????????public?void?run() {

????????????????System.out.printf(name);

????????????????for?(int?i =?0; i <?100; i++) {

????????????????????TestDemo a = list.get(i);

????????????????????synchronized?(a) {

????????????????????????if?(a == list.get(10)) {

????????????????????????????System.out.println("t2 i=10 get(1)預期是無鎖"?+ ClassLayout.parseInstance(list.get(1)).toPrintable());//偏向鎖

????????????????????????????System.out.println("t2 i=10 get(10) 預期輕量級鎖 "?+ i + ClassLayout.parseInstance(a).toPrintable());//偏向鎖

????????????????????????}

????????????????????????if?(a == list.get(19)) {

????????????????????????????System.out.println("t2? i=19? get(10)預期是無鎖"?+?10?+ ClassLayout.parseInstance(list.get(10)).toPrintable());//偏向鎖

????????????????????????????System.out.println("t2? i=19? get(19) 滿足重偏向條件20 預期偏向鎖 "?+ i + ClassLayout.parseInstance(a).toPrintable());//偏向鎖

????????????????????????????System.out.println("類的對象累計撤銷達到20");

????????????????????????}?

????????????????????}

????????????????}

????????????????try?{

????????????????????Thread.sleep(100000);

????????????????}?catch?(InterruptedException e) {

????????????????????e.printStackTrace();

????????????????}

????????????}

????????};

????????t2.start();

????????Thread.sleep(5000);

??

????????Thread t3 =?new?Thread() {

????????????String name =?"3";

????????????public?void?run() {

????????????????System.out.printf(name);

????????????????for?(TestDemo a : list2) {

????????????????????synchronized?(a) {

????????????????????????if?(a == list2.get(10)) {

????????????????????????????System.out.println("t3 預期是偏向鎖"?+?10?+ ClassLayout.parseInstance(a).toPrintable());//偏向鎖

????????????????????????}

????????????????????}

????????????????}

????????????????try?{

????????????????????Thread.sleep(100000);

????????????????}?catch?(InterruptedException e) {

????????????????????e.printStackTrace();

????????????????}

????????????}

????????};

????????t3.start();

????????Thread.sleep(5000);

??

????????Thread t4 =?new?Thread() {

????????????String name =?"4";

????????????public?void?run() {

????????????????System.out.printf(name);

????????????????for?(int?i =?0; i <?100; i++) {

????????????????????TestDemo a = list2.get(i);

????????????????????synchronized?(a) {

????????????????????????if?(a == list2.get(10)) {

????????????????????????????System.out.println("t4 i=10 get(1)預期是無鎖"?+ ClassLayout.parseInstance(list2.get(1)).toPrintable());//偏向鎖

????????????????????????????System.out.println("t4 i=10 get(10) 當前不滿足重偏向條件 20 預期輕量級鎖 "?+ i + ClassLayout.parseInstance(a).toPrintable());//偏向鎖

????????????????????????}

????????????????????????if?(a == list2.get(19)) {

????????????????????????????System.out.println("t4? i=19? get(10)預期是無鎖"?+?10?+ ClassLayout.parseInstance(list2.get(10)).toPrintable());//偏向鎖

????????????????????????????System.out.println("t4 i=19 get(19) 當前滿足重偏向條件 20 但A類的對象累計撤銷達到40 預期輕量級鎖 "?+ i + ClassLayout.parseInstance(a).toPrintable());//偏向鎖

????????????????????????????System.out.println("類的對象累計撤銷達到40");

????????????????????????}

????????????????????????if?(a == list2.get(20)) {

????????????????????????????System.out.println("t4 i=20 get(20) 當前滿足重偏向條件 20 預期輕量級鎖 "?+ i + ClassLayout.parseInstance(a).toPrintable());//偏向鎖

????????????????????????}

????????????????????}

????????????????}

????????????}

????????};

????????t4.start();

????????Thread.sleep(5000);

????????System.out.println("main 預期是偏向鎖"?+?10?+ ClassLayout.parseInstance(list3.get(0)).toPrintable());//偏向鎖

????????Thread t5 =?new?Thread() {

????????????String name =?"5";

????????????public?void?run() {

????????????????System.out.printf(name);

????????????????for?(TestDemo a : list3) {

????????????????????synchronized?(a) {

????????????????????????if?(a == list3.get(10)) {

????????????????????????????System.out.println("t5 預期是輕量級鎖,類的對象累計撤銷達到40 不可以用偏向鎖了"?+?10?+ ClassLayout.parseInstance(a).toPrintable());//偏向鎖

????????????????????????}

????????????????????}

????????????????}

????????????????try?{

????????????????????Thread.sleep(100000);

????????????????}?catch?(InterruptedException e) {

????????????????????e.printStackTrace();

????????????????}

????????????}

????????};

????????t5.start();

????????Thread.sleep(5000);

????????System.out.println("main 預期是偏向鎖"?+?10?+ ClassLayout.parseInstance(list.get(10)).toPrintable());//偏向鎖

??

????????Thread t6 =?new?Thread() {

????????????String name =?"6";

????????????public?void?run() {

????????????????System.out.printf(name);

????????????????for?(int?i =?0; i <?100; i++) {

????????????????????TestDemo a = list3.get(i);

????????????????????synchronized?(a) {

????????????????????????if?(a == list3.get(10)) {

????????????????????????????System.out.println("t6 i=10 get(1)預期是無鎖"?+ ClassLayout.parseInstance(list3.get(1)).toPrintable());//偏向鎖

????????????????????????????System.out.println("t6 i=10 get(10) 預期輕量級鎖 "?+ i + ClassLayout.parseInstance(a).toPrintable());//偏向鎖

????????????????????????}

????????????????????????if?(a == list3.get(19)) {

????????????????????????????System.out.println("t6? i=19? get(10)預期是無鎖"?+?10?+ ClassLayout.parseInstance(list3.get(10)).toPrintable());//偏向鎖

????????????????????????????System.out.println("t6? i=19? get(19) 滿足重偏向條件20 但類的對象累計撤銷達到40 不可以用偏向鎖了 "?+ i + ClassLayout.parseInstance(a).toPrintable());//偏向鎖

????????????????????????}

????????????????????}

????????????????}

??

????????????????try?{

????????????????????Thread.sleep(100000);

????????????????}?catch?(InterruptedException e) {

????????????????????e.printStackTrace();

????????????????}

????????????}

????????};

????????t6.start();

????????Thread.sleep(5000);

??

????????System.out.println("由于撤銷鎖次數達到默認的 BiasedLockingBulkRevokeThreshold=40 這里實例化的對象 是無鎖狀態"?+ ClassLayout.parseInstance(new?TestDemo()).toPrintable());//偏向鎖

     System.out.println("撤銷偏向后狀態"?+?10?+ ClassLayout.parseInstance(new?TestDemo()).toPrintable());//偏向鎖

  }

}

   

運行結果:

初始狀態10?com.boke.TestDemo object internals:

OFFSET??SIZE???TYPE DESCRIPTION???????????????????????????????VALUE

??????0????12????????(object header)???????????????????????????N/A

?????12?????4????????(loss due to the next object alignment)

Instance size: 16 bytes

Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

?

?

1t1 預期是偏向鎖10?com.boke.TestDemo object internals:

OFFSET??SIZE???TYPE DESCRIPTION???????????????????????????????VALUE

??????0?????4????????(object header)???????????????????????????05 e0 86 8e (00000101?11100000 10000110 10001110) (-1903763451)

??????4?????4????????(object header)???????????????????????????ec 7f 00 00 (11101100 01111111 00000000 00000000) (32748)

??????8?????4????????(object header)???????????????????????????bf c3 00 f8 (10111111 11000011 00000000 11111000) (-134167617)

?????12?????4????????(loss due to the next object alignment)

Instance size: 16 bytes

Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

?

?

main 預期是偏向鎖10?com.boke.TestDemo object internals:

OFFSET??SIZE???TYPE DESCRIPTION???????????????????????????????VALUE

??????0?????4????????(object header)???????????????????????????05 e0 86 8e (00000101?11100000 10000110 10001110) (-1903763451)

??????4?????4????????(object header)???????????????????????????ec 7f 00 00 (11101100 01111111 00000000 00000000) (32748)

??????8?????4????????(object header)???????????????????????????bf c3 00 f8 (10111111 11000011 00000000 11111000) (-134167617)

?????12?????4????????(loss due to the next object alignment)

Instance size: 16 bytes

Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

?

?

2t2 i=10 get(1)預期是無鎖com.boke.TestDemo object internals:

OFFSET??SIZE???TYPE DESCRIPTION???????????????????????????????VALUE

??????0?????4????????(object header)???????????????????????????01 00 00 00 (00000001?00000000 00000000 00000000) (1)

??????4?????4????????(object header)???????????????????????????00 00 00 00 (00000000 00000000 00000000 00000000) (0)

??????8?????4????????(object header)???????????????????????????bf c3 00 f8 (10111111 11000011 00000000 11111000) (-134167617)

?????12?????4????????(loss due to the next object alignment)

Instance size: 16 bytes

Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

?

?

t2 i=10 get(10) 預期輕量級鎖 10?com.boke.TestDemo object internals:

OFFSET??SIZE???TYPE DESCRIPTION???????????????????????????????VALUE

??????0?????4????????(object header)???????????????????????????08 99 7a 03 (00001000?10011001 01111010 00000011) (58366216)

??????4?????4????????(object header)???????????????????????????00 70 00 00 (00000000 01110000 00000000 00000000) (28672)

??????8?????4????????(object header)???????????????????????????bf c3 00 f8 (10111111 11000011 00000000 11111000) (-134167617)

?????12?????4????????(loss due to the next object alignment)

Instance size: 16 bytes

Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

?

?

t2??i=19??get(10)預期是無鎖10?com.boke.TestDemo object internals:

OFFSET??SIZE???TYPE DESCRIPTION???????????????????????????????VALUE

??????0?????4????????(object header)???????????????????????????01 00 00 00 (00000001?00000000 00000000 00000000) (1)

??????4?????4????????(object header)???????????????????????????00 00 00 00 (00000000 00000000 00000000 00000000) (0)

??????8?????4????????(object header)???????????????????????????bf c3 00 f8 (10111111 11000011 00000000 11111000) (-134167617)

?????12?????4????????(loss due to the next object alignment)

Instance size: 16 bytes

Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

?

?

t2??i=19??get(19) 滿足重偏向條件20?預期偏向鎖 19com.boke.TestDemo object internals:

OFFSET??SIZE???TYPE DESCRIPTION???????????????????????????????VALUE

??????0?????4????????(object header)???????????????????????????05 09 90 91 (00000101?00001001 10010000 10010001) (-1852831483)

??????4?????4????????(object header)???????????????????????????ec 7f 00 00 (11101100 01111111 00000000 00000000) (32748)

??????8?????4????????(object header)???????????????????????????bf c3 00 f8 (10111111 11000011 00000000 11111000) (-134167617)

?????12?????4????????(loss due to the next object alignment)

Instance size: 16 bytes

Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

?

?

類的對象累計撤銷達到20

3t3 預期是偏向鎖10com.boke.TestDemo object internals:

OFFSET??SIZE???TYPE DESCRIPTION???????????????????????????????VALUE

??????0?????4????????(object header)???????????????????????????05 09 89 90 (00000101?00001001 10001001 10010000) (-1870067451)

??????4?????4????????(object header)???????????????????????????ec 7f 00 00 (11101100 01111111 00000000 00000000) (32748)

??????8?????4????????(object header)???????????????????????????bf c3 00 f8 (10111111 11000011 00000000 11111000) (-134167617)

?????12?????4????????(loss due to the next object alignment)

Instance size: 16 bytes

Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

?

?

4t4 i=10 get(1)預期是無鎖com.boke.TestDemo object internals:

OFFSET??SIZE???TYPE DESCRIPTION???????????????????????????????VALUE

??????0?????4????????(object header)???????????????????????????01 00 00 00 (00000001?00000000 00000000 00000000) (1)

??????4?????4????????(object header)???????????????????????????00 00 00 00 (00000000 00000000 00000000 00000000) (0)

??????8?????4????????(object header)???????????????????????????bf c3 00 f8 (10111111 11000011 00000000 11111000) (-134167617)

?????12?????4????????(loss due to the next object alignment)

Instance size: 16 bytes

Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

?

?

t4 i=10 get(10) 當前不滿足重偏向條件 20 預期輕量級鎖?10com.boke.TestDemo object internals:

OFFSET??SIZE???TYPE DESCRIPTION???????????????????????????????VALUE

??????0?????4????????(object header)???????????????????????????08 f9 9a 03 (00001000?11111001 10011010 00000011) (60487944)

??????4?????4????????(object header)???????????????????????????00 70 00 00 (00000000 01110000 00000000 00000000) (28672)

??????8?????4????????(object header)???????????????????????????bf c3 00 f8 (10111111 11000011 00000000 11111000) (-134167617)

?????12?????4????????(loss due to the next object alignment)

Instance size: 16 bytes

Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

?

?

t4??i=19??get(10)預期是無鎖10com.boke.TestDemo object internals:

OFFSET??SIZE???TYPE DESCRIPTION???????????????????????????????VALUE

??????0?????4????????(object header)???????????????????????????01 00 00 00 (00000001?00000000 00000000 00000000) (1)

??????4?????4????????(object header)???????????????????????????00 00 00 00 (00000000 00000000 00000000 00000000) (0)

??????8?????4????????(object header)???????????????????????????bf c3 00 f8 (10111111 11000011 00000000 11111000) (-134167617)

?????12?????4????????(loss due to the next object alignment)

Instance size: 16 bytes

Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

?

?

t4 i=19 get(19) 當前滿足重偏向條件 20 但A類的對象累計撤銷達到40 預期輕量級鎖?19com.boke.TestDemo object internals:

OFFSET??SIZE???TYPE DESCRIPTION???????????????????????????????VALUE

??????0?????4????????(object header)???????????????????????????08 f9 9a 03 (00001000?11111001 10011010 00000011) (60487944)

??????4?????4????????(object header)???????????????????????????00 70 00 00 (00000000 01110000 00000000 00000000) (28672)

??????8?????4????????(object header)???????????????????????????bf c3 00 f8 (10111111 11000011 00000000 11111000) (-134167617)

?????12?????4????????(loss due to the next object alignment)

Instance size: 16 bytes

Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

?

?

類的對象累計撤銷達到40

t4 i=20 get(20) 當前滿足重偏向條件 20 預期輕量級鎖 20com.boke.TestDemo object internals:

OFFSET??SIZE???TYPE DESCRIPTION???????????????????????????????VALUE

??????0?????4????????(object header)???????????????????????????08 f9 9a 03 (00001000?11111001 10011010 00000011) (60487944)

??????4?????4????????(object header)???????????????????????????00 70 00 00 (00000000 01110000 00000000 00000000) (28672)

??????8?????4????????(object header)???????????????????????????bf c3 00 f8 (10111111 11000011 00000000 11111000) (-134167617)

?????12?????4????????(loss due to the next object alignment)

Instance size: 16 bytes

Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

?

?

main 預期是偏向鎖10com.boke.TestDemo object internals:

OFFSET??SIZE???TYPE DESCRIPTION???????????????????????????????VALUE

??????0?????4????????(object header)???????????????????????????05 00 00 00 (00000101?00000000 00000000 00000000) (5)

??????4?????4????????(object header)???????????????????????????00 00 00 00 (00000000 00000000 00000000 00000000) (0)

??????8?????4????????(object header)???????????????????????????bf c3 00 f8 (10111111 11000011 00000000 11111000) (-134167617)

?????12?????4????????(loss due to the next object alignment)

Instance size: 16 bytes

Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

?

?

5t5 預期是輕量級鎖,A類的對象累計撤銷達到40 不可以用偏向鎖了10com.boke.TestDemo object internals:

OFFSET??SIZE???TYPE DESCRIPTION???????????????????????????????VALUE

??????0?????4????????(object header)???????????????????????????08 f9 9a 03 (00001000?11111001 10011010 00000011) (60487944)

??????4?????4????????(object header)???????????????????????????00 70 00 00 (00000000 01110000 00000000 00000000) (28672)

??????8?????4????????(object header)???????????????????????????bf c3 00 f8 (10111111 11000011 00000000 11111000) (-134167617)

?????12?????4????????(loss due to the next object alignment)

Instance size: 16 bytes

Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

?

?

main 預期是偏向鎖10com.boke.TestDemo object internals:

OFFSET??SIZE???TYPE DESCRIPTION???????????????????????????????VALUE

??????0?????4????????(object header)???????????????????????????01 00 00 00 (00000001?00000000 00000000 00000000) (1)

??????4?????4????????(object header)???????????????????????????00 00 00 00 (00000000 00000000 00000000 00000000) (0)

??????8?????4????????(object header)???????????????????????????bf c3 00 f8 (10111111 11000011 00000000 11111000) (-134167617)

?????12?????4????????(loss due to the next object alignment)

Instance size: 16 bytes

Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

?

?

6t6 i=10 get(1)預期是無鎖com.boke.TestDemo object internals:

OFFSET??SIZE???TYPE DESCRIPTION???????????????????????????????VALUE

??????0?????4????????(object header)???????????????????????????01 00 00 00 (00000001?00000000 00000000 00000000) (1)

??????4?????4????????(object header)???????????????????????????00 00 00 00 (00000000 00000000 00000000 00000000) (0)

??????8?????4????????(object header)???????????????????????????bf c3 00 f8 (10111111 11000011 00000000 11111000) (-134167617)

?????12?????4????????(loss due to the next object alignment)

Instance size: 16 bytes

Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

?

?

t6 i=10 get(10) 預期輕量級鎖 10com.boke.TestDemo object internals:

OFFSET??SIZE???TYPE DESCRIPTION???????????????????????????????VALUE

??????0?????4????????(object header)???????????????????????????08 29 ab 03 (00001000?00101001 10101011 00000011) (61548808)

??????4?????4????????(object header)???????????????????????????00 70 00 00 (00000000 01110000 00000000 00000000) (28672)

??????8?????4????????(object header)???????????????????????????bf c3 00 f8 (10111111 11000011 00000000 11111000) (-134167617)

?????12?????4????????(loss due to the next object alignment)

Instance size: 16 bytes

Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

?

?

t6??i=19??get(10)預期是無鎖10com.boke.TestDemo object internals:

OFFSET??SIZE???TYPE DESCRIPTION???????????????????????????????VALUE

??????0?????4????????(object header)???????????????????????????01 00 00 00 (00000001?00000000 00000000 00000000) (1)

??????4?????4????????(object header)???????????????????????????00 00 00 00 (00000000 00000000 00000000 00000000) (0)

??????8?????4????????(object header)???????????????????????????bf c3 00 f8 (10111111 11000011 00000000 11111000) (-134167617)

?????12?????4????????(loss due to the next object alignment)

Instance size: 16 bytes

Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

?

?

t6??i=19??get(19) 滿足重偏向條件20 但A類的對象累計撤銷達到40 不可以用偏向鎖了?19com.boke.TestDemo object internals:

OFFSET??SIZE???TYPE DESCRIPTION???????????????????????????????VALUE

??????0?????4????????(object header)???????????????????????????08 29 ab 03 (00001000?00101001 10101011 00000011) (61548808)

??????4?????4????????(object header)???????????????????????????00 70 00 00 (00000000 01110000 00000000 00000000) (28672)

??????8?????4????????(object header)???????????????????????????bf c3 00 f8 (10111111 11000011 00000000 11111000) (-134167617)

?????12?????4????????(loss due to the next object alignment)

Instance size: 16 bytes

Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

?

?

由于類撤銷鎖次數達到默認的 BiasedLockingBulkRevokeThreshold=40 這里實例化的對象 是無鎖狀態com.boke.TestDemo object internals:

OFFSET??SIZE???TYPE DESCRIPTION???????????????????????????????VALUE

??????0?????4????????(object header)???????????????????????????01 00 00 00 (00000001?00000000 00000000 00000000) (1)

??????4?????4????????(object header)???????????????????????????00 00 00 00 (00000000 00000000 00000000 00000000) (0)

??????8?????4????????(object header)???????????????????????????bf c3 00 f8 (10111111 11000011 00000000 11111000) (-134167617)

?????12?????4????????(loss due to the next object alignment)

Instance size: 16 bytes

Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

?

?

撤銷偏向后狀態10com.boke.TestDemo object internals:
OFFSET SIZE TYPE DESCRIPTION                     VALUE
  0    4        (object header)                01 00 00 00 (00000001?00000000 00000000 00000000) (1)
  4    4        (object header)               00 00 00 00 (00000000 00000000 00000000 00000000) (0)
  8    4        (object header)                bf c3 00 f8 (10111111 11000011 00000000 11111000) (-134167617)
  12   4        (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

?

以上案例證實了偏向鎖的批量重偏向和批量撤銷,接下來我們講解輕量級鎖;

?


?

輕量級鎖:

?

  • 當鎖是偏向鎖的時候,被另外的線程所訪問,偏向鎖就會升級為輕量級鎖,其他線程會通過自旋的形式嘗試獲取鎖,不會阻塞,從而提高性能。
  • 在代碼進入同步塊的時候,如果同步對象鎖狀態為無鎖狀態(鎖標志位為“01”狀態,是否為偏向鎖為“0”),虛擬機首先將在當前線程的棧幀中建立一個名為鎖記錄(Lock Record)的空間,用于存儲鎖對象目前的Mark Word的拷貝,然后拷貝對象頭中的Mark Word復制到鎖記錄中。
  • 拷貝成功后,虛擬機將使用CAS操作嘗試將對象的Mark Word更新為指向Lock Record的指針,并將Lock Record里的owner指針指向對象的Mark Word。
  • 如果這個更新動作成功了,那么這個線程就擁有了該對象的鎖,并且對象Mark Word的鎖標志位設置為“00”,表示此對象處于輕量級鎖定狀態。
  • 如果輕量級鎖的更新操作失敗了,虛擬機首先會檢查對象的Mark Word是否指向當前線程的棧幀,如果是就說明當前線程已經擁有了這個對象的鎖,那就可以直接進入同步塊繼續執行,否則說明多個線程競爭鎖。
  • 若當前只有一個等待線程,則該線程通過自旋進行等待。但是當自旋超過一定的次數,或者一個線程在持有鎖,一個在自旋,又有第三個來訪時,輕量級鎖升級為重量級鎖。
  • 多個線程在不同的時間段請求同一把鎖,也就是說沒有鎖競爭。針對這種情形,Java 虛擬機采用了輕量級鎖,來避免重量級鎖的阻塞以及喚醒
  • 在沒有鎖競爭的前提下,減少傳統鎖使用OS互斥量產生的性能損耗
  • 在競爭激烈時,輕量級鎖會多做很多額外操作,導致性能下降
  • 可以認為兩個線程交替執行的情況下請求同一把鎖

?

分析一個由偏向鎖膨脹成輕量級鎖的案例:

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

public?class?TestDemo {

}

public?class?DemoExample9 {

????public?static?void?main(String[] args)?throws?Exception {

????????TestDemo testDemo =?new?TestDemo();

??

????????//子線程

????????Thread t1 =?new?Thread(){

????????????@Override

????????????public?void?run() {

????????????????synchronized?(testDemo){

????????????????????System.out.println("t1 lock ing");

????????????????????System.out.println(ClassLayout.parseInstance(testDemo).toPrintable());

????????????????}

????????????}

????????};

?????????

????????t1.join();

??

????????//主線程

????????synchronized?(testDemo){

????????????System.out.println("main lock ing");

????????????System.out.println(ClassLayout.parseInstance(testDemo).toPrintable());

????????}

??

????}

}

  

運行結果(兩個線程交替執行的情況下):

main lock ing

com.boke.TestDemo object internals:

OFFSET??SIZE???TYPE DESCRIPTION???????????????????????????????VALUE

??????0?????4????????(object header)???????????????????????????e8 48 95 09 (11101000?01001000 10010101 00001001) (160778472)

??????4?????4????????(object header)???????????????????????????00 70 00 00 (00000000 01110000 00000000 00000000) (28672)

??????8?????4????????(object header)???????????????????????????a0 c1 00 f8 (10100000 11000001 00000000 11111000) (-134168160)

?????12?????4????????(loss due to the next object alignment)

Instance size: 16 bytes

Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

?


?

重量級鎖:

?

  • 多個線程競爭同一個鎖的時候,虛擬機會阻塞加鎖失敗的線程,并且在目標鎖被釋放的時候,喚醒這些線程;
  • Java 線程的阻塞以及喚醒,都是依靠操作系統來完成的:os?pthread_mutex_lock()?;
  • 升級為重量級鎖時,鎖標志的狀態值變為“10”,此時Mark Word中存儲的是指向重量級鎖的指針,此時等待鎖的線程都會進入阻塞狀態

??

分析一個由輕量級鎖膨脹成重量級鎖的案例:

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

public?class?TestDemo {

}

public?class?DemoExample9 {

????public?static?void?main(String[] args)?throws?Exception {

????????TestDemo testDemo =?new?TestDemo();

??

??

????????Thread t1 =?new?Thread(){

????????????@Override

????????????public?void?run() {

????????????????synchronized?(testDemo){

????????????????????System.out.println("t1 lock ing");

????????????????????System.out.println(ClassLayout.parseInstance(testDemo).toPrintable());

????????????????}

????????????}

????????};

??

????????t1.start();

??

????????synchronized?(testDemo){

????????????System.out.println("main lock ing");

????????????System.out.println(ClassLayout.parseInstance(testDemo).toPrintable());

????????}

????}

}

?

?運行結果:

main lock ing

com.boke.TestDemo object internals:

OFFSET??SIZE???TYPE DESCRIPTION???????????????????????????????VALUE

??????0?????4????????(object header)???????????????????????????5a ad 00 b0 (01011010?10101101 00000000 10110000) (-1342132902)

??????4?????4????????(object header)???????????????????????????cf 7f 00 00 (11001111 01111111 00000000 00000000) (32719)

??????8?????4????????(object header)???????????????????????????a0 c1 00 f8 (10100000 11000001 00000000 11111000) (-134168160)

?????12?????4????????(loss due to the next object alignment)

Instance size: 16 bytes

Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

?

?

t1 lock ing

com.boke.TestDemo object internals:

OFFSET??SIZE???TYPE DESCRIPTION???????????????????????????????VALUE

??????0?????4????????(object header)???????????????????????????5a ad 00 b0 (01011010?10101101 00000000 10110000) (-1342132902)

??????4?????4????????(object header)???????????????????????????cf 7f 00 00 (11001111 01111111 00000000 00000000) (32719)

??????8?????4????????(object header)???????????????????????????a0 c1 00 f8 (10100000 11000001 00000000 11111000) (-134168160)

?????12?????4????????(loss due to the next object alignment)


?

我們再來說一下Java 虛擬機是怎么區分輕量級鎖和重量級鎖的:

  • 當進行加鎖操作時,Java 虛擬機會判斷是否已經是重量級鎖。如果不是,它會在當前線程的當前棧楨中劃出一塊空間,作為該鎖的鎖記錄,并且將鎖對象的標記字段復制到該鎖記錄中。

  • 然后,Java 虛擬機會嘗試用 CAS(compare-and-swap)操作替換鎖對象的標記字段。這里解釋一下,CAS 是一個原子操作,它會比較目標地址的值是否和期望值相等,如果相等,則替換為一個新的值。

  • 假設當前鎖對象的標記字段為 X…XYZ,Java 虛擬機會比較該字段是否為 X…X01。如果是,則替換為剛才分配的鎖記錄的地址。由于內存對齊的緣故,它的最后兩位為 00。此時,該線程已成功獲得這把鎖,可以繼續執行了。

  • 如果不是 X…X01,那么有兩種可能。第一,該線程重復獲取同一把鎖。此時,Java 虛擬機會將鎖記錄清零,以代表該鎖被重復獲取。第二,其他線程持有該鎖。此時,Java 虛擬機會將這把鎖膨脹為重量級鎖,并且阻塞當前線程。

  • 當進行解鎖操作時,如果當前鎖記錄(你可以將一個線程的所有鎖記錄想象成一個棧結構,每次加鎖壓入一條鎖記錄,解鎖彈出一條鎖記錄,當前鎖記錄指的便是棧頂的鎖記錄)的值為 0,則代表重復進入同一把鎖,直接返回即可。

  • 否則,Java 虛擬機會嘗試用 CAS 操作,比較鎖對象的標記字段的值是否為當前鎖記錄的地址。如果是,則替換為鎖記錄中的值,也就是鎖對象原本的標記字段。此時,該線程已經成

  • 功釋放這把鎖。

  • 如果不是,則意味著這把鎖已經被膨脹為重量級鎖。此時,Java 虛擬機會進入重量級鎖的釋放過程,喚醒因競爭該鎖而被阻塞了的線程

?


?

到此為止本篇就講完了鎖的膨脹過程

?

?

總結一下

  1. 偏向鎖只會在第一次請求時采用 CAS 操作,在鎖對象的標記字段中記錄下當前線程的地址。在之后的運行過程中,持有該偏向鎖的線程的加鎖操作將直接返回。它針對的是鎖僅會被同一線程持有的情況。

  2. 輕量級鎖采用 CAS 操作,將鎖對象的標記字段替換為一個指針,指向當前線程棧上的一塊空間,存儲著鎖對象原本的標記字段。它針對的是多個線程在不同時間段申請同一把鎖的情況。

  3. 重量級鎖會阻塞、喚醒請求加鎖的線程。它針對的是多個線程同時競爭同一把鎖的情況。Java 虛擬機采取了自適應自旋,來避免線程在面對非常小的 synchronized 代碼塊時,仍會被阻塞、喚醒的情況。

?


?

?

說完了鎖的膨脹過程,那么會不會有鎖的降級呢?

?

我在hotspot源碼中找到了這樣的注釋:

// We create a list of in-use monitors for each thread.//// deflate_thread_local_monitors() scans a single thread's in-use list, while// deflate_idle_monitors() scans only a global list of in-use monitors which// is populated only as a thread dies (see omFlush()).//// These operations are called at all safepoints, immediately after mutators// are stopped, but before any objects have moved. Collectively they traverse// the population of in-use monitors, deflating where possible. The scavenged// monitors are returned to the monitor free list.//// Beware that we scavenge at *every* stop-the-world point. Having a large// number of monitors in-use could negatively impact performance. We also want// to minimize the total # of monitors in circulation, as they incur a small// footprint penalty.//// Perversely, the heap size -- and thus the STW?safepoint?rate --// typically drives the scavenge rate.??Large heaps can mean infrequent GC,// which in turn can mean large(r) numbers of objectmonitors in circulation.// This is an unfortunate aspect of this design.//大概意思是:鎖降級確實是會發生的,當 JVM 進入安全點(SafePoint)的時候,會檢查是否有閑置的 Monitor,然后試圖進行降級有興趣的大佬可以在https://hg.openjdk.java.net/jdk/jdk/file/896e80158d35/src/hotspot/share/runtime/synchronizer.cpp鏈接中:研究一下deflate_idle_monitors是分析鎖降級邏輯的入口,這部分行為還在進行持續改進,因為其邏輯是在安全點內運行,處理不當可能拖長 JVM 停頓(STW,stop-the-world)的時間。

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/386485.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/386485.shtml
英文地址,請注明出處:http://en.pswp.cn/news/386485.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

System.Configuration命名空間下的關鍵類

1.ConfigurationManager和 WebConfigurationManager類&#xff1a; 使用 ConfigurationManager 類&#xff0c;可以訪問計算機和應用程序的配置信息。ConfigurationManager 是處理客戶端應用程序配置文件的首選方法&#xff1b;不推薦使用任何其他方法。對于 Web 應用程序&…

連續四年百度Android崗必問面試題!Android校招面試指南

前言 剛從阿里面試回來&#xff0c;想和大家分享一些我的面試經驗&#xff0c;以及面試題目。 這篇文章將會更加聚焦在面試前需要看哪些資料&#xff0c;一些面試技巧以及一些這次的面試考題。 面試經歷 7月確定想走后開始看各種面經&#xff0c;復習基礎知識&#xff0c;月…

Spring Boot教程(11) – 理解注解@ControllerAdvice

之前&#xff0c;我們介紹過ModelAttribute和ExceptionHandler,前者可以往請求的Model里加數據&#xff0c;后者可以接受請求處理方法拋出的異常。但是他們放在控制器(Controller)里的時候&#xff0c;作用范圍是有限的&#xff0c;只管當前控制器里的方法。如果你有幾百個控制…

透徹解析!字節跳動Android實習面試涼涼經,年薪超過80萬!

什么是Kotlin? Kotlin&#xff0c;如前面所說&#xff0c;它是JetBrains開發的基于JVM的語言。JetBrains因為創造了一個強大的Java開發IDE被大家所熟知。Android Studio&#xff0c;官方的Android IDE&#xff0c;就是基于Intellij&#xff0c;作為一個該平臺的插件。 Kotli…

synchronized 底層如何實現?什么是鎖升級、降級?

synchronized 底層如何實現&#xff1f;什么是鎖升級、降級&#xff1f; synchronized 代碼塊是由一對 monitorenter/monitorexit 指令實現的&#xff0c;Monitor 對象是同步的基本實現單元。 https://docs.oracle.com/javase/specs/jls/se10/html/jls-8.html#d5e13622 在Jav…

Spring主要用到兩種設計模式

Spring主要用到兩種設計模式 1、工廠模式 Spring容器就是實例化和管理全部Bean的工廠。 工廠模式可以將Java對象的調用者從被調用者的實現邏輯中分離出來。 調用者只關心被調用者必須滿足的某種規則&#xff0c;這里的規則我們可以看做是接口&#xff0c;而不必關心實例的具體實…

意外收獲字節跳動內部資料,已開源

前言 每年的3、4月份是各大企業為明年拓展業務大量吸納人才的關鍵時期&#xff0c;招聘需求集中、空缺崗位多&#xff0c;用人單位也習慣在初秋進行大規模招聘。 金九銀十&#xff0c;招聘旺季&#xff0c;也是一個求職旺季。 不打無準備的仗&#xff0c;在這種關鍵時期&…

OpenJDK研究

這里以32位Windows 7為例 安裝必須的軟件 JDK1.8CygwinMicrosoft Visual Studio 2010 (請下載英文版) 這里就不介紹怎么安裝這些軟件了&#xff0c;假設安裝后的目錄名分別是: (請根據你的實際情況調整這些目錄名&#xff09; D:\JavaSE1.8 D:\Cygwin D:\VS2010 增加環境變…

獵頭文章(一)

&#xff08;一&#xff09;從來沒有想過自己會加入這一行&#xff0c; 從開始自己喜歡的專業通訊&#xff0c; 到后來喜歡的管理&#xff0c;&#xff0c;幻想過是專業高手&#xff0c; 幻想過管理專家&#xff0c; 卻從來沒有想過進入這一行&#xff0c;但 真的在我剛剛離開校…

成功跳槽百度工資從15K漲到28K,威力加強版

前言 看到一篇文章中提到“最近幾年國內的初級Android程序員已經很多了&#xff0c;但是中高級的Android技術人才仍然稀缺“&#xff0c;這的確不假&#xff0c;從我在百度所進行的一些面試來看&#xff0c;找一個適合的高級Android工程師的確不容易&#xff0c;一般需要進行大…

Redis下載及安裝(windows版)

下載地址 1、Github下載地址&#xff1a;https://github.com/MicrosoftArchive/redis/releases 2、百度網盤下載地址 https://pan.baidu.com/s/1z1_OdNVbtgyEjiktqgB83g 密碼&#xff1a;kdfq 安裝過程 1.首先先把下載的壓縮包解壓到一個文件夾中 2.打開cmd指令窗口 3.輸入你剛…

成功跳槽百度工資從15K漲到28K,跳槽薪資翻倍

前言 這篇文章主要是分享今年上半年的面試心得&#xff0c;現已就職于某大廠有三個月了&#xff0c;近期有很多公司均已啟動秋招&#xff0c;也祝大家在 2020 的下半年面試順利&#xff0c;獲得理想的offer&#xff01; 之前找工作的那段時間感想頗多&#xff0c;總結一點面試…

分布式鎖RedLock的java實現Redisson

1. 概述Redisson是一個在Redis的基礎上實現的Java駐內存數據網格&#xff08;In-Memory Data Grid&#xff09;。它不僅提供了一系列的分布式的Java常用對象&#xff0c;還提供了許多分布式服務。其中包括(BitSet, Set, Multimap, SortedSet, Map, List, Queue, BlockingQueue,…

我三年開發經驗,從字節跳動抖音離職后,看看這篇文章吧!

最新BAT大廠面試者整理的Android面試題目&#xff01; 近期根據網友分享大廠面試題目&#xff0c;今天我將網友面試的BAT等大廠Android面試題目整理出來&#xff0c;希望能夠幫助大家&#xff01; 珍藏版&#xff08;1&#xff09;——高級 UI 晉升 第一節、觸摸事件分發機制…

arthas命令redefine實現Java熱更新

Arthas非常重要的命令redefine&#xff0c;主要作用是加載外部的.class文件&#xff0c;用來替換JVM已經加載的類&#xff0c;總結起來就是實現了Java的熱更新。 redefine在一下幾種情況中會失敗&#xff1a;1、增加了field&#xff1b;2、增加了method&#xff1b;3、替換正在…

安裝 ZendServer-CE 可能遇到的問題

安裝后,打開http://localhost:10081/ZendServer 出現如下頁面. Internal Server Error The server encountered an internal error or misconfiguration and was unable to complete your request. Please contact the server administrator, adminexample.com and inform them…

Elk7.2 Docker

正如官方所說的那樣 https://www.elastic.co/guide/en/elasticsearch/reference/current/vm-max-map-count.html&#xff0c;Elasticsearch默認使用mmapfs目錄來存儲索引。操作系統默認的mmap計數太低可能導致內存不足&#xff0c;我們可以使用下面這條命令來增加內存 為了防止…

我了解到的面試的一些小內幕!附面試題答案

背景 首先我是個菜雞&#xff0c;工資也低的一筆。 剛畢業時候在一家國企上班干 app 開發&#xff0c;干了快兩年的時候&#xff0c;跳槽到了一家偽大廠干安全。投了不少簡歷都沒有回音&#xff0c;只有這加偽大廠要我就來了。當時說好了會接觸一些底層的東西&#xff0c;然而…

學習單調隊列小結

因為一直在聽身邊的人說什么單調隊列/斜率優化dp/背包&#xff0c;(ps:我也不清楚這樣稱呼對不對&#xff0c;因為我真心是沒見過這些東西)我都覺得那是神一樣的東西。終于抽出時間學了一下。 昨天在朋友一本書里面看到一句話&#xff0c;這里先跟大家分享一下&#xff1a; 沒有…

@Async join

直接貼代碼 自定義線程池 package com.xh.lawsuit.rest.modular.example; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecu…