vijay
vijay

Reputation: 75

Java Synchronization - Mutex.wait vs List.wait

While using Java Threading Primitives to construct a thread safe bounded queue - whats the difference between these 2 constructs

  1. Creating an explicit lock object.
  2. Using the list as the lock and waiting on it.

Example of 1

private final Object lock = new Object();
private ArrayList<String> list = new ArrayList<String>();

public String dequeue() {
    synchronized (lock) {
        while (list.size() == 0) {
            lock.wait();
        }

        String value = list.remove(0);
        lock.notifyAll();
        return value;
    }
}    

public void enqueue(String value) {
    synchronized (lock) {
        while (list.size() == maxSize) {
            lock.wait();
        }

        list.add(value);
        lock.notifyAll();
    }
}

Example of 2

private ArrayList<String> list = new ArrayList<String>();

public String dequeue() {
    synchronized (list) {  // lock on list
        while (list.size() == 0) {
           list.wait();     // wait on list
        }

        String value = list.remove(0);
        list.notifyAll();  
        return value;
    }
}


public void enqueue(String value) {
    synchronized (list) {  // lock on list
        while (list.size() == maxSize) {
           list.wait();   // wait on list
        }

        list.add(value);
        list.notifyAll();
    }
}

Note

  1. This is a bounded list
  2. No other operation is being performed apart from enqueue and dequeue.
  3. I could use a blocking queue, but this question is more for improving my limited knowledge of threading.
  4. If this question is repeated please let me know.

Upvotes: 4

Views: 3419

Answers (1)

CodeBlind
CodeBlind

Reputation: 4569

The short answer is, no, there is no functional difference, other than the extra memory overhead of maintaining that extra lock object. However, there are a couple of semantics-related items I would consider before making a final decision.

Will I ever need to perform synchronized operations on more than just my internal list?

Let's say you wanted to maintain a parallel data structure to your ArrayList, such that all operations on the list and that parallel data structure needed to be synchronized. In this case, it might be best to use the external lock, as locking on either the list or the structure might be confusing to future development efforts on this class.

Will I ever give access to my list outside of my queue class?

Let's say you wanted to provide an accessor method for your list, or make it visible to extensions of your Queue class. If you were using an external lock object, classes that retrieved references to the list would never be able to perform thread-safe operations on that list. In that case, it'd be better to synchronize on the list and make it clear in the API that external accesses/modifications to the list must also synchronize on that list.

I'm sure there are more reasons why you might choose one over the other, but these are the two big ones I can think of.

Upvotes: 5

Related Questions