[英]how to synchronize a set of multiple threads with respect to a single thread in Java
假設我有一個名為myList of threads的arraylist,所有這些都是使用實現Runnable接口的類myRunnable的實例創建的,也就是說,所有線程共享相同的代碼以在myRunnable的run()方法中執行。 現在假設我有另一個名為singleThread的線程,該線程是使用實現Runnable接口的類otherRunnable的實例創建的。
我必須為這些線程解決的同步化挑戰如下:我需要myList中的所有線程執行它們的代碼直到某一點。 一旦達到這一點,他們就會睡覺。 一旦所有且只有myList中的所有線程都處於休眠狀態,那么應該喚醒singleThread(singleThread已經處於休眠狀態)。 然后singleThread執行它自己的東西,當它完成時,它應該睡眠並且myList中的所有線程都應該被喚醒。 想象一下,代碼被包含在while(true)中,所以這個過程必須一次又一次地發生。
以下是我剛才描述的情況示例,包括嘗試解決同步問題:
class myRunnable extends Runnable
{
public static final Object lock = new Object();
static int count = 0;
@override
run()
{
while(true)
{
//do stuff
barrier();
//do stuff
}
}
void barrier()
{
try {
synchronized(lock) {
count++;
if (count == Program.myList.size()) {
count = 0;
synchronized(otherRunnable.lock) {
otherRunnable.lock.notify();
}
}
lock.wait();
}
} catch (InterruptedException ex) {}
}
}
class otherRunnable extend Runnable
{
public static final Object lock = new Object();
@override
run()
{
while(true)
{
try {
synchronized(lock) {
lock.wait();
} catch (InterruptedException ex) {}
// do stuff
try {
synchronized(myRunnable.lock) {
myRunnable.notifyAll();
}
}
}
}
class Program
{
public static ArrayList<Thread> myList;
public static void main (string[] args)
{
myList = new ArrayList<Thread>();
for(int i = 0; i < 10; i++)
{
myList.add(new Thread(new myRunnable()));
myList.get(i).start();
}
new Thread(new OtherRunnable()).start();
}
}
基本上我的想法是使用一個計數器來確保myList中的線程只是等待,除了最后一個線程遞增計數器,它將計數器重置為0,通過通知鎖定喚醒singleThread,然后最后一個線程進入睡眠狀態等到myRunnable.lock。 在更抽象的層面上,我的方法是在myList中為線程使用某種屏障來阻止它們在關鍵點執行,然后擊中屏障的最后一個線程喚醒singleThread並進入睡眠狀態,然后singleThread使其成為東西完成后,它會喚醒屏障中的所有線程,以便它們可以再次繼續。
我的問題是我的邏輯存在缺陷(可能還有更多)。 當最后一個線程觸及屏障通知otherRunnable.lock時,有可能發生直接上下文切換,在最后一個線程可以在myRunnable.lock上執行其等待(並進入休眠狀態)之前將cpu提供給singleThread。 然后singleThread將執行它的所有東西,將在myRunnable.lock上執行notifyAll,並且myList中的所有線程將被喚醒,除了最后一個線程擊中屏障,因為它尚未執行其wait命令。 然后,所有這些線程將再次執行它們的內容並再次觸及屏障,但計數永遠不會等於myList.size(),因為前面提到的最后一個線程最終會再次調度並執行wait。 反過來,singleThread也會在第一行執行wait,結果導致死鎖,每個人都在睡覺。
所以我的問題是:什么是同步這些線程的好方法,以實現之前描述的所需行為,但同時以一種安全的死鎖方式?
根據您的評論,聽起來像CyclicBarrier完全符合您的需求。 從文檔(強調我的):
一種同步輔助工具, 允許一組線程全部等待彼此到達公共障礙點 。 CyclicBarriers在涉及固定大小的線程方的程序中很有用,這些線程必須偶爾等待彼此。 屏障稱為循環,因為它可以在等待線程釋放后重新使用 。
不幸的是,我自己沒有使用它們,所以我不能給你具體的指示。 我認為基本的想法是使用帶有barrierAction
的雙參數構造函數構造barrierAction
。 完成此任務后,在此屏障上有n
線程await()
,之后執行barrierAction
,之后n
線程將繼續。
來自CyclicBarrier#await()
的javadoc:
如果當前線程是要到達的最后一個線程,並且在構造函數中提供了非null屏障操作,則當前線程在允許其他線程繼續之前運行該操作。 如果在屏障操作期間發生異常,則該異常將在當前線程中傳播,並且屏障處於斷開狀態。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.