Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does Java `synchronized` block lock on Object reference, or value?

Given the output shown below:

    Path path1 = Paths.get("/Users/someone/foo");
    Path path2 = Paths.get("/Users/someone/foo");
    System.out.println(path1.toString() == path2.toString()); // outputs false
    System.out.println(path1.toString().equals(path2.toString())); // outputs true

Given the following two threads, is it possible for both threads to be running in the critical section at the same time?

    // Thread 1
    synchronized (path1.toString()) {
        // Critical section
    }

    // Thread 2
    synchronized (path2.toString()) {
        // Critical section
    }
like image 960
albusshin Avatar asked Oct 21 '25 04:10

albusshin


2 Answers

The reference is the value. This is a distinction without a difference. toString() is a reference. It won't be the same as any other toString() value unless both have been interned, or they both originated from identical or the same string literals.

like image 50
user207421 Avatar answered Oct 23 '25 17:10

user207421


As is documented in the Java Language Specification, section 14.19 (JLS), the synchronized statement locks on objects. If you're thinking of "value" as the string value (as in path1.toString().equals(path2.toString())), then then answer is "no"—your code is almost certainly not thread-safe. In the parlance of the JLS, if the type of an expression is a reference type (as required for the synchronized statement), then the value of that expression is either null or an object. The two blocks in your posted code are not mutually exclusive unless the two toString() calls return the same object reference (path1.toString() == path2.toString()).

like image 33
Ted Hopp Avatar answered Oct 23 '25 19:10

Ted Hopp