我必须在哪里使用同步?

Where do i have to use synchronized?

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

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

情况是我有一个方法,其中 Thread 用于创建 ArrayList。在同一个 Thread 中,另一个 methodBufferedReader 完成读取文件并将行添加到第一个列表后被调用。

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

这是我使用的代码,如果有什么不清楚的地方请询问,我会尽力提供所需的信息。

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

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

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

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

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

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

假设您的方法是在一个名为 Sample 的 class 中定义的,并且您已经创建了一个实例 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();
}