WonderWorld
WonderWorld

Reputation: 966

Where do i have to use synchronized?

I have done some research and could not find a solution to this problem.

From this topic Synchronization, When to or not to use? i understand i could use synchronized, but doing so doesn't solve the problem.

The case is that i have a method in which a Thread is used to create an ArrayList. In that same Thread another method is called after a BufferedReader has finished reading a file and the lines are being added to the first List.

In the second method the first list is being used to create the second List. When all that is done, the first method uses the second list.

This is somewhat the code i use, if there is something not clear please ask and i will try to provide the info needed.

public synchronized void theBaseList() {
    Thread t = new Thread() {
        @override
        public void run() {
          try(
              while((line = br.readLine()) != null) {
                  firstList.add(line):
              }
          }
          nextMethod();
          currentObject = (Object[]) secondList.get(0); // throws an exception
          }
      }
  };
  t.start();

public synchronized void nextMethod() {
    Thread t1 = new Thread(){
        double objectListSize = calculateObjectListLength(firstList.size());
        @override
        public void run() {
          try {
              // create Objects
              secondList.add(objects);
            }
         }
      };
      t1.start();
}

When i use a Thread in nextMethod() to create a new list of Objects from the items in the first list, i get an ArrayIndexOutOfBoundsException saying

Exception in thread "Thread-4" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0

I avoided this by not using a Thread in the second method and all works fine.

If i do use 2 Threads and make both methods synchronized, it still throws the exception.

Is it possible or should i just settle by not using a Thread in the second method? I thought synchronized was for dealing with this sort of problems. I don't understand why it doesn't work.

Upvotes: 0

Views: 116

Answers (1)

chiaboy
chiaboy

Reputation: 384

Let's say your methods are defined in a class named Sample and you've created an instance mySample. This appears to be what your code is doing:

main thread calls mySample.theBaseList() and synchronizes by locking on mySample.
  theBaseList() defines thread1 and starts it.
  theBaseList() exits scope, thus unlocking on mySample.

thread1 reads in the lines of a file and adds them to list1 (these operations are not synchronized)
thread1 calls mySample.nextMethod()
mySample.nextMethod() synchronizes by locking on mySample
    nextMethod() defines thread2 and starts it.
    nextMethod() exits scope, thus unlocking on mySample.

* thread2 sets up list2 (these operations are not synchronized)
* thread1, having returned from nextMethod() reads from list2 (these operations are not synchronized)

The last two operations are the cause of your race condition.

In your case, using synchronized methods is perhaps too coarse grained. A better option may be to synchronize on the object on which both threads operate, secondList.

nextMethod();
synchronized(secondList) {
    currentObject = (Object[]) secondList.get(0); // should no longer throw an exception
}

synchronized(secondList) {
    // create Objects
    secondList.add(objects);
}

EDIT:

synchronized(secondList) {
    nextMethod();
    secondList.wait();
    currentObject = (Object[]) secondList.get(0); // should no longer throw an exception
}

synchronized(secondList) {
    // create Objects
    secondList.add(objects);
    secondList.notifyAll();
}

Upvotes: 2

Related Questions