2

How can I synchronize 2 threads to handle data in a list ?

  • thread A is adding / changing items in a list (writing to the list)
  • thread B is displaying the items (only reading the list)

I would like to "notify" thread B when it can display the list. In the time of reading the list it must not be changed by thread A. When thread B is done reading, thread A can start changing the list again.

My guesses go to

  • synchronized(obj)
  • list.wait() + list.notify()

Threads aren't invoking each other. They run concurrent all the time.

Bitterblue
  • 13,162
  • 17
  • 86
  • 124

4 Answers4

0

You could put all changes in Runnables and put them in a queue that Thread A executes in order. After each job, A must generate a snapshot of the modified list and submit it to Thread B. You could use Executors for that.

Ralf H
  • 1,392
  • 1
  • 9
  • 17
0

General concept (as I see it in your case) would be as follows.

1) Create an instance of List that you're planning to work with.

2) Write 2 classes corresponding to your thread A and thread B that both implement Runnable and take List as their constructor parameter.

3) Synchronize these 2 classes on list instance:

// method in class that adds
public void add() {
  synchronized(list) {
    // perform addition ...
    list.notify();
  }
}

// method in class that reads
public void read() throws InterruptedException {
  synchronized(list) {
    while (list.isEmpty())
      list.wait();
    // process data ...
  }
}

4) Create 2 threads with argumens corresponding to instances of these 2 classes and start them.

Andrew Logvinov
  • 21,181
  • 6
  • 52
  • 54
  • That's what I was trying to do but always ended up in deadlocks, IllegalMonitoExceptions or unsynchronized execution. I'll go with ReentrantLock since it works well. – Bitterblue Apr 30 '13 at 10:11
0

I tried concurrency packages suggested here or here and it works well. The threads lock each other out:

final Lock lock = new ReentrantLock(true);

// thread A
lock.lock();
// write to list
lock.unlock();

// thread B
lock.lock();
// read from list
lock.unlock();

Not sure if they can execute precisely one after another and I didn't get the notify feature. But that doesn't hurt my application.

Community
  • 1
  • 1
Bitterblue
  • 13,162
  • 17
  • 86
  • 124
0

Reader and writer locks are your friends here.

•thread A is adding / changing items in a list (writing to the list)

... so it can use the write lock ...

•thread B is displaying the items (only reading the list)

... so it can use the read lock.

Let's assume that you're using something straight forward for your wait/notify (for example, the built-in Object methods) to block the read and display thread. At that point, your code looks something like this:

/** This is the read/write lock that both threads can see */
private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

/** This method is called by thread A (the writer / modifier) */
public void add() {
    try {
        // Only one writer at a time allowed
        lock.writeLock().lock();
        // Insert code here: Add to the list 
    } finally {
        // Unlock in the finally block to ensure that lock is released
        lock.writeLock().unlock();
    }
    // Notify anyone who's waiting for data
    list.notify();
}

/** This method is called by thread B (the reader / displayer) */
public void read() throws InterruptedException {
    try {
        // As many readers as you like at a time
        lock.readLock().lock();
        // Insert code here: read from the list
    } finally {
        // Unlock in the finally block to ensure that lock is released
        lock.readLock().unlock();
    }
    // Wait for new data
    list.wait();
}

To make things even more convenient, you can get rid of the notify/wait messaging by using a blocking data structure: e.g., one of the BlockingQueues. In that case, you don't write any notification at all. The reader blocks waiting for new data. When the writer adds data to the queue, the reader unblocks, drains the new data to process, does its thing and then blocks again.

Bob Cross
  • 22,116
  • 12
  • 58
  • 95
  • Interesting. But the Q was simpler (to just synchronize reader and writer). Or does this have some benefits over the simple ReentrantLock ? – Bitterblue Apr 07 '14 at 07:47
  • @mini-me, yes, if you have a situation where readers and writers are not balanced: e.g., more readers than writers, writing takes less time than reading or other examples. There's extra logic in the read/write locks: arbitrary numbers of readers vs. only one writer, no more readers if a writer requests a lock, etc. – Bob Cross Apr 07 '14 at 11:46