1. 程式人生 > >對String在多執行緒中的一些簡單認識

對String在多執行緒中的一些簡單認識

  最近在看多執行緒,synchronized程式碼塊時候說到用String物件來當作鎖,然後說最好不要用String物件來當作鎖,這是為什麼了?可以先看一段程式。

public class StringLock {

    public void method() {
        //new String("字串常量")
        synchronized ("字串常量") {
            try {
                while(true){
                    System.out.println("當前執行緒 : "  +    Thread.currentThread().getName() + "開始"
); Thread.sleep(1000); System.out.println("當前執行緒 : " + Thread.currentThread().getName() + "結束"); } } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main
(String[] args) { final StringLock stringLock = new StringLock(); Thread t1 = new Thread(new Runnable() { @Override public void run() { stringLock.method(); } },"t1"); Thread t2 = new Thread(new Runnable() { @Override
public void run() { stringLock.method(); } },"t2"); t1.start(); t2.start(); } }

程式執行的結果(部分)是:
  當前執行緒 : t1開始
  當前執行緒 : t1結束
不斷輸出這兩句話,這是為什麼了?因為鎖"字串常量"是一個常量鎖,當你將鎖"字串常量"改成new String("字串常量"),控制檯會輸出什麼了,t2執行緒也可以開始運行了。程式執行的結果(部分)是:
  當前執行緒 : t1開始
  當前執行緒 : t2開始
  當前執行緒 : t2結束
  當前執行緒 : t1結束
這是因為new String("字串常量")建立的是不同的物件,所以鎖不同,兩個執行緒都能執行。這讓我想起了我們剛學java的時候有一些書本上會講到這個列子:

public static void main(String[] args) {
        String s1 = new String("hello");
        String s2 = "hello";

        System.out.println(s1 == s2);// false
        System.out.println(s1.equals(s2));// true
    }

  new String("hello")"hello"是兩個不同的物件,一個是儲存在常量池中,一個是儲存在堆中。有些時候業務上就是需要傳入一個new String的物件鎖了,可以將鎖改成new String("字串常量").intern(),這個鎖的本質其實和"字串常量"這個鎖是一樣的。
  看看jdk的文件說的:一個初始為空的字串池,它由類 String 私有地維護。 當呼叫 intern 方法時,如果池已經包含一個等於此 String 物件的字串(用 equals(Object) 方法確定),則返回池中的字串。否則,將此 String 物件新增到池中,並返回此 String 物件的引用。
  對於String物件鎖在業務上的例子可以參考這篇博文https://www.cnblogs.com/xrq730/p/6662232.html