user485498
user485498

Reputation:

Java and Synchronizing two threads

I have two threads modifying the same objects. The objects are custom, non-synchronized objects in an ArrayList (not a vector). I want to make these two threads work nicely together, since they are called at the same time.

Here is the only important method in thread 1.

public void doThread1Action() {
  //something...
  for(myObject x : MyArrayList){
    modify(x);
  }
}

Here is a method in thread 2:

public void doThread2Action() {   
  //something...
  for(myObject x : MyArrayList){
    modifyAgain(x);
  }
}

At the moment, when testing, I occasionally get `ConcurrentModificationExceptions``. (I think it depends on how fast thread 1 finishes its iterations, before thread 2 tries to modify the objects.)

Am I right in thinking that by simply appending synchronized to the beginning of these two methods, the threads will work together in a synchronized way and not try to access the ArrayList? Or should I change the ArrayList to a Vector?

Upvotes: 1

Views: 215

Answers (4)

Sam
Sam

Reputation: 6900

I guess your problem is related to ConcurrentModificationException. This class in its Java docs says:

/**
* This exception may be thrown by methods that have detected concurrent
* modification of an object when such modification is not permissible.

*/

In your case, problem is iterator in a list and may modified. I guess by following implementation your problem will sole:

public void doThread1Action()
{
    synchronized(x //for sample)
    {
       //something...
       for(myObject x : MyArrayList)
       {
          modify(x);
       }
    }
}

and then:

public void doThread2Action()
{
    synchronized(x //for sample)
    {
       //something...
       for(myObject x : MyArrayList)
       {
          modifyAgain(x);
       }
    }
}

For take better result I want anyone correct my solution.

Upvotes: 0

Robert
Robert

Reputation: 8609

You need to sychronsize access to the collection on the same lock, so just using synchronized keyword on the methods (assuming they are in different classes) would be locking on two different objects.

so here is an example of what you might need to do:

Object lock = new Object();

public void doThread1Action(){

//something...
    synchronized(lock){
        for(myObject x : MyArrayList){
           modify(x);
    }

}

public void doThread2Action(){

//something...
    synchronized(lock){
        for(myObject x : MyArrayList){
            modifyAgain(x);
    }

}

Also you could consider using a CopyOnWriteArrayList instead of Vector

Upvotes: 0

barfuin
barfuin

Reputation: 17494

You do not need to synchronize access to the list as long as you don't modify it structurally, i.e. as long as you don't add or remove objects from the list. You also shouldn't see ConcurrentModificationExceptions, because these are only thrown when you structurally modify the list.

So, assuming that you only modify the objects contained in the list, but you do not add or remove or reorder objects on the list, it is possible to synchronize on the contained objects whenever you modify them, like so:

void modifyAgain(MyObject x) {
    synchronized(x) {
        // do the modification
    }
}

I would not use the synchronized modifier on the modifyAgain() method, as that would not allow two distinct objects in the list to be modified concurrently.

The modify() method in the other thread must of course be implemented in the same way as modifyAgain().

Upvotes: 0

mtraut
mtraut

Reputation: 4740

A ConcurrentModificationException does not stem from modifying objects in a collection but from adding / removing from a collection while an iterator is active.

The shared resources is the collection and there must be a third method using and add/remove. To get concurrency right you must synchronize access to the collection resource in all methods that access it.

To avoid overly long synchronized blocks a common pattern may be to copy the collection in a synchronized block and then iterate over it. If you do it this way, be aware the problem you are talking about in first place (concurrent modification of your object) is again in place - but this time you can lock on another resource.

Upvotes: 3

Related Questions