首先讓我們來(lái)看看下面的代碼

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

start sleep
get lock
現(xiàn)在,讓我們來(lái)看看,實(shí)際運(yùn)行的結(jié)果又是如何呢?當(dāng)運(yùn)行這段代碼時(shí),輸出如下圖所示:

為什么沒(méi)有輸出get lock 呢?讓我們?cè)趤?lái)看看這個(gè)這兩個(gè)線程都在處理什么?打印線程堆棧如下:
"printLockThread" prio=6 tid=0x02b13800 nid=0x284 waiting for monitor entry [0x02eaf000..0x02eafd14]
java.lang.Thread.State: BLOCKED (on object monitor)
at net.blogjava.narry.stringlock.StringLockTest$Test2.printHoldLock(StringLockTest.java:61)
- waiting to lock <0x26a2b918> (a java.lang.String)
at net.blogjava.narry.stringlock.StringLockTest$Test2.access$1(StringLockTest.java:59)
at net.blogjava.narry.stringlock.StringLockTest$2.run(StringLockTest.java:25)
at java.lang.Thread.run(Thread.java:619)
Locked ownable synchronizers:
- None
"holdLockThread" prio=6 tid=0x02b12800 nid=0x1d8 waiting on condition [0x02e5f000..0x02e5fd94]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at net.blogjava.narry.stringlock.StringLockTest$Test1.holdLock(StringLockTest.java:48)
- locked <0x26a2b918> (a java.lang.String)
at net.blogjava.narry.stringlock.StringLockTest$1.run(StringLockTest.java:15)
at java.lang.Thread.run(Thread.java:619)
Locked ownable synchronizers:
- None
如果將上面的代碼修改如下:

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

比較上面的兩段代碼的區(qū)別,僅僅在于在類Test1,將private String lock="stringLock"修改成了private String lock=new String("stringLock");
通過(guò)上面的比較,其實(shí)反應(yīng)了一個(gè)比較老的話題:String類的創(chuàng)建方式和在JVM中存儲(chǔ)的方式
String對(duì)象的創(chuàng)建有兩種方式通過(guò)""和通過(guò)new String()來(lái)創(chuàng)建,通過(guò)雙引號(hào)來(lái)創(chuàng)建的String對(duì)象的信息存放在的Constant Pool中,我們將在Constant Pool中存放String的區(qū)域叫做String Pool,在運(yùn)行期時(shí),相同字符串的引用都指向String Pool中的相同的對(duì)象;而通過(guò)new方法創(chuàng)建的對(duì)象,會(huì)分別在heap上開(kāi)辟存儲(chǔ)空間,作為不同的對(duì)象存在,說(shuō)道這里大家可能已經(jīng)清楚為什么會(huì)出現(xiàn)上面例子中的現(xiàn)象了。
所以,如果采用字符串作為L(zhǎng)ock,并且當(dāng)創(chuàng)建的方式為“”時(shí),就可能出現(xiàn)兩個(gè)方面的問(wèn)題:
1)增加了程序中不相關(guān)的部分的串行的運(yùn)行的幾率,降低了并發(fā)度
2)增加了程序中出現(xiàn)死鎖的可能性
但是,這個(gè)特性在某個(gè)時(shí)候也能進(jìn)行利用,因?yàn)橥ㄟ^(guò)String.intern方法我們可以獲得String對(duì)象在String Pool中所對(duì)應(yīng)的對(duì)象或者是將自己加入到String Pool中,所以舉個(gè)例子,如果需要將日志記錄到不同的文件中,而且在每條日志的開(kāi)始的部分有標(biāo)識(shí)所要寫入日志的記錄文件的標(biāo)志,因?yàn)閷懭氲较嗤募娜罩臼且械模晕覀兙涂梢酝ㄟ^(guò)使用每條日志中的記錄文件的標(biāo)志的String.intern()為lock,實(shí)現(xiàn)在記錄到相同文件日志之間的串行記錄,不同文件的日志之間的并行記錄(注:此處只是舉例,不要在實(shí)際環(huán)境中使用,對(duì)于這種情況使用隊(duì)列應(yīng)該更合適)。