Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Synchronization Lock

When we say we lock on an object using the synchronized keyword, does it mean we are acquiring a lock on the whole object or only at the code that exists in the block?

In the following example listOne.add is synchronized, does it mean if another thread accesses listOne.get it would be blocked until the first thread gets out of this block? What if a second thread accesses the listTwo.get or listTwo.add methods on the instance variables of the same object when the first thread is still in the synchronized block?

List<String> listONe = new ArrayList<String>();
List<String> listTwo = new ArrayList<String>();

/* ... ... ... */

synchronized(this) {
    listOne.add(something);
}
like image 524
Abidi Avatar asked Dec 04 '22 09:12

Abidi


1 Answers

Given the methods:

  public void a(String s) {
    synchronized(this) {
      listOne.add(s);
    }
  }

  public void b(String s) {
    synchronized(this) {
      listTwo.add(s);
    }
  }

  public void c(String s) {
      listOne.add(s);
  }

  public void d(String s) {
      synchronized(listOne) {
        listOne.add(s);
      }
  }

You can not call a and b at the same time, as they are locked on the same lock. You can however call a and c at the same time (with multiple threads obviously) as they are not locked on the same lock. This can lead to trouble with listOne.

You can also call a and d at the same time, as d is no different in this context from c. It does not use the same lock.

It is important that you always lock listOne with the same lock, and allow no access to it without a lock. If listOne and listTwo are somehow related and sometimes need updates at the same time / atomically you'd need one lock for access to both of them. Otherwise 2 separate locks may be better.

Of course, you'd probably use the relatively new java.util.concurrent classes if all you need is a concurrent list :)

like image 51
extraneon Avatar answered Dec 15 '22 18:12

extraneon