2015-04-21 46 views
6

我有这样的情况(这是Java的伪代码):如何同步2个池线程之间的数组切换?

有其主线程:

1)创建C型的阵列的一个实例:

C[] arr = new C[LARGE]; 

2)创建并提交其填充任务(通过做CPU绑定操作)的ARR到池P1:

for (int i = 0; i < populateThreadCount; i++) { 
    p1.submit(new PopulateTask(arr, start, end)) 
} 

每个任务填充不同范围indexe的因此此时池P1中的线程之间不需要同步。 3)主线程等待所有填充任务完成。

4)一旦ARR填充,主线程创建和提交其上传(IO绑定操作)ARR的内容,到池P2任务:

for (int i = 0; i < uploadThreadCount; i++) { 
    p2.submit(new UploadTask(arr, start, end); 
} 

如前所述,该范围是不重叠,每个线程都有自己的范围,所以P2池中的线程之间不需要内部同步。

在填充和上传任务中,范围不同,因为有不同数量的线程来处理每种类型。

现在我在想什么是最有效的同步方法。

使用CopyOnWriteArrayList不是一个选项,因为它可能非常大(数百万个元素)。

我最初的想法是简单地在填入任务创建一个C类的实例后,上传任务同步,然后以相同:

C[] arr = new C[LARGE]; 

for (int i = 0; i < populateThreadCount; i++) { 
p1.submit(new PopulateTask(arr, start, end) { 

    void run() { 
    for (int j = start; j <= end; j++) { 
    ... do some heavy computation ... 
    arr[j] = new C(some_computed_data); 
    synchronized(arr[j]) {} 
    } 
    } 

}); 
} 

for (int i = 0; i < uploadThreadCount; i++) { 
p2.submit(new UploadTask(arr, start, end) { 

    void run() { 
    for (int j = start; j <= end; j++) { 
    synchronized(arr[j]) { 
    upload(arr[j]); 
    } 
    } 
    } 

}); 
} 

,但不知道这是正确的,特别是如果这个空的同步块不会被javac或JIT优化。 在开始填充任务之前,我无法创建C类的实例,因为我需要计算的数据。

任何想法,如果这是正确的,如果不是一个更好的方法?

+0

我不明白你想要同步什么,为什么。 –

+0

@JBNizet:(S)他试图确保UploadTask实例不会尝试上传PopulateTask实例尚未完成填充的数组元素。 – ruakh

+0

“3)主线程等待所有填充任务完成。”如果是这种情况,那么我不会看到有什么要同步。 – Arkadiy

回答

2

你不需要同步任何东西。执行者提供您需要的内存可视性保证。特别是看到concurrent package documentation:提交一个Runnable之前

  • 操作在一个线程的执行器发生-before其执行开始。同样可以将Callables提交给ExecutorService。
  • 通过Future.get()在另一个线程中检索结果之后的Future happen-before动作所代表的异步计算采取的操作。

因此,通过提交第一执行人执行人已完成执行它们(第二条规则)后,主线程做什么之前发生的,并且任务完成的改变是什么主线程确实与阵列发生在提交给第二执行者的任务(第一条规则)执行的动作之前。

既然发生在传递之前,提交给第二个执行者的任务将看到提交给第一个任务的任务所做的更改。

+0

有道理。我已经从上面的伪代码中跳过了,但这是我实际上等待任务完成的方式 - 我抓取所有由提交返回的期货,将它们放入数组中,并且一旦提交了所有的期货,我就分别调用.get()他们在主线程中。 – Janek

+0

虽然可以让执行程序通过调用invokeAll()来为您执行此操作,但这没关系:http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ExecutorService.html#invokeAll% 28java.util.Collection 29% –