Блокировка на струнах - PullRequest
       5

Блокировка на струнах

0 голосов
/ 21 октября 2010

2 вопроса:

  1. Поле str используется двумя экземплярами типа A [строка 2]
  2. Какое значение имеет следующий код?

class A implements Runnable {
    String str = "hello"; // line 2.

    public void run(){
        Synchronized(str){
            System.out.println(str+" "+Thread.currentThread().getName());
            Thread.sleep(100);
            System.out.println(str+" "+Thread.currentThread().getName());
            //anything
        }
    }

    public void static main(String[] args){  
        Thread one = new Thread(new A(),"one").start();  
        Thread two = new Thread(new A(),"two").start();  
    }
}

Ответы [ 2 ]

10 голосов
/ 21 октября 2010

Само поле не является общим для двух экземпляров. Это разные поля. Однако они начинаются с того же значения, что и строковые литералы интернированные.

Это означает, что когда блок synchronized получает монитор строки в одном потоке, он не позволит другому потоку получить тот же монитор. Важно понимать, что блок synchronized получает блокировку для монитора, связанного со значением поля - не имеет значения, что задействованы два отдельных поля.

Мораль: не синхронизировать строки, особенно литералы. Литералы особенно плохи, потому что в этом случае у вас может быть другой класс с тем же кодом, что и A, и также попытается синхронизировать, используя тот же монитор.

4 голосов
/ 21 октября 2010

Блокировка строк таким образом может быть опасной. Согласно Разделу 3.10.5 Спецификации языка Java :

Буквальные строки в разных классы в разных пакетах аналогично представлять ссылки на то же самое String объект.

Это означает, что если другой класс содержит тот же строковый литерал, он будет ссылаться на тот же объект String и может привести к тупику.

Лучше использовать одну из явных блокировок из java.util.concurrent.locks или даже new Object().

Пример:

private final ReentrantLock lock = new ReentrantLock();
String str = "hello";    

public void run(){
    lock.lock(); 
    try{
        System.out.println(str+" "+Thread.currentThread().getName());
        Thread.sleep(100);
        System.out.println(str+" "+Thread.currentThread().getName());
    }
    finally{
        lock.unlock();
    }

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...