我在哪里必须使用同步?

时间:2015-03-27 01:19:35

标签: java multithreading synchronized

我做了一些研究,找不到解决这个问题的方法。

从这个主题Synchronization, When to or not to use?我知道我可以使用synchronized,但这样做并不能解决问题。

案例是我有一种方法,其中Thread用于创建ArrayList。同样Threadmethod读完文件后将调用另一个BufferedReader,并将这些行添加到第一个列表中。

在第二种方法中,第一个列表用于创建第二个List。完成所有操作后,第一种方法使用第二个列表。

这有点像我使用的代码,如果有不清楚的地方请询问,我会尝试提供所需的信息。

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();
}

当我使用Thread中的nextMethod()从第一个列表中的项目创建新的list个对象时,我会得到一个ArrayIndexOutOfBoundsException

  

线程中的异常"线程-4" java.lang.IndexOutOfBoundsException:Index:0,Size:0

我通过在第二种方法中不使用Thread来避免这种情况,并且一切正常。

如果我确实使用2 Threads并使两个方法synchronized,它仍会抛出异常。

是否有可能或者我应该通过在第二种方法中不使用Thread来解决问题?我认为synchronized是为了解决这类问题。我不明白为什么它不起作用。

1 个答案:

答案 0 :(得分:2)

假设您的方法是在名为Sample的类中定义的,并且您已创建了一个实例mySample。这似乎是您的代码正在做的事情:

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)

最后两项操作是导致竞争状况的原因。

在您的情况下,使用同步方法可能过于粗糙。一个更好的选择可能是在两个线程运行的对象上同步,secondList。

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

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

编辑:

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();
}