0

2 Questions:

  1. str field is shared between two instance of A type [line 2]
  2. What's implications according to following code ?

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();  
    }
}
FixMaker
  • 3,759
  • 3
  • 26
  • 44
MineIsMine
  • 424
  • 2
  • 10
  • 20
  • Possible duplicate of [Synchronizing on String objects in Java](https://stackoverflow.com/questions/133988/synchronizing-on-string-objects-in-java) – Vadzim Nov 11 '17 at 18:36

2 Answers2

10

The field itself isn't shared between two instances. They are distinct fields. However, they start off with the same value, as string literals are interned.

That means when the synchronized block acquires the string's monitor in one thread, it will prevent the other thread from acquiring the same monitor. It's important to understand that the synchronized block is acquiring the lock for the monitor associated with the value of the field - it doesn't matter that there are two separate fields involved.

Moral: don't synchronize on strings, particularly literals. Literals are particularly bad, because in this case you could have another class with the same code as A, and that would also try to synchronize using the same monitor.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • you said `it doesn't matter that there are two separate fields` I think just in **immutable classes** case -- Right?? – MineIsMine Oct 21 '10 at 07:55
  • 1
    @MinelsMine: Not really - because it's only the values that matter. Who cares whether the field values *can* change if they never *do* actually change? – Jon Skeet Oct 21 '10 at 08:27
  • (And even if they do change, it's the value *at the point of lock acquisition* which is important.) – Jon Skeet Oct 21 '10 at 08:43
4

Locking on strings in this manner can be dangerous. According to Section 3.10.5 of the Java Language Specification:

Literal strings within different classes in different packages likewise represent references to the same String object.

What this means is that if another class contains the same string literal, it will refer to the same String object and could result in a deadlock.

It would be better to use one of the explicit locks from the java.util.concurrent.locks package or even a new Object().

Example:

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();
    }

}
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
dogbane
  • 266,786
  • 75
  • 396
  • 414