Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java. How to properly synchronize getters and setters?

If I have several mutable properties in an object that will be acted upon by several threads, I understand they should be synchronized.

class Doggie {
    private String name;
    private int    age;

    public void setName(String name) { this.name = name; }
    public String getName() { return this.name; }
    public void setAge(int age) { this.age = age; }
    public int getAge() { return this.age; }

}

Questions:

  • Are not return and assignment atomic operations in Java?
  • Since properties might not necessarily be interrelated, it does not always make sense to synchronize with the same lock. How to organize the locking structure?
  • Is it better to go with the intrinsic lock or a private Object lock pattern?
like image 391
Jake Avatar asked Jun 19 '10 15:06

Jake


3 Answers

  • Are not return and assignment atomic operations in Java?

Yes they are atomic (in some cases at least), but atomicity is not the only issue. Another important issue is whether the action of a write to an attribute by one thread is guaranteed to be visible to a following read for the same attribute made by a different thread.

  • When the reads and writes are in the same thread, the read is guaranteed to see the earlier write.

  • When the reads and writes are in different threads, the read is only guaranteed to see the earlier write if the two threads synchronize properly ... or if the attribute is declared as volatile.

Note that primitive locks/mutexes are not the only way to synchronize.

  • Since properties might not necessarily be interrelated, it does not always make sense to synchronize with the same lock. How to organize the locking structure?

It makes sense to use multiple locks if (and only if) lock contention is likely. In your example, lock contention is only likely to be an issue if some Doggie instance receives a very high rate of get and/or set operations.

  • Is it better to go with the intrinsic lock or a private Object lock pattern?

It depends. If your application is going use the Doggie object's primitive lock, then you might get lock contention or even unintended locking out of get and set operations. In that case a private lock might be advisable. Otherwise, a private lock is an unnecessary overhead.

like image 186
Stephen C Avatar answered Oct 02 '22 07:10

Stephen C


Your example begs for an immutable object. http://java.sun.com/docs/books/tutorial/essential/concurrency/imstrat.html

like image 43
Romain Hippeau Avatar answered Oct 02 '22 08:10

Romain Hippeau


Operations with references are atomic, but not volatile - you will always see the old value or the new value, but there's no guarantee you'll see the new value without some sort of memory barrier. I can't remember the details of which primitives are guaranteed to be atomic - probably all but long and double.

Personally I'd use a single private lock until I saw any evidence that it was a bottleneck. I would advise against locking on "this" as other code might lock on it too. If you're the only code that knows about the lock, it's harder to get interference. Having said that, if callers want to atomically change more than one property, you may want to expose the lock via a property.

Do you definitely need a threadsafe mutable type? If you could avoid that requirement it would make life simpler.

like image 30
Jon Skeet Avatar answered Oct 02 '22 07:10

Jon Skeet