假設我有一個名爲線程myList的數組列表,所有這些都是使用實現Runnable接口的類myRunnable的一個實例創建的,也就是說,線程共享相同的代碼以在myRunnable的run()方法中執行。現在假設我有另一個叫做singleThread的單線程,它是使用實現Runnable接口的類otherRunnable的一個實例創建的。如何在Java中爲一個線程同步一組多線程
我必須爲這些線程解決的同步挑戰如下:我需要myList中的所有線程來執行它們的代碼,直到某個點。一旦達到這一點,他們就睡着了。一旦myList中的所有線程都處於睡眠狀態,則應該喚醒singleThread(singleThread已經睡着)。然後singleThread執行它自己的東西,當它完成時,它應該休眠並且myList中的所有線程都應該被喚醒。想象一下,這些代碼被封裝在(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,有一個機會,立即上下文切換可能發生,這給CPU到singleThread,前最後一個線程可以在myRunnable.lock執行的等待(和睡覺)。然後singleThread將執行所有的東西,將在myRunnable.lock執行notifyAll的,並在myList中的所有線程將被喚醒,除了最後一個線程打擊,因爲它尚未執行的等待命令的屏障。然後,所有的線程會再次這樣做自己的東西,並會再次命中障礙,但數量將永遠等於myList.size(),因爲前面提到的最後一個線程最終會被再次安排和將執行的等待。單線程反過來也會在第一行執行等待,結果導致我們陷入僵局,每個人都在睡覺。
所以我的問題是:什麼將這些線程,以達到在某種程度上安全死鎖的同一時間之前,但在描述所期望的行爲同步的好辦法?
tl; dr您可以對您嘗試解決的問題提供更高級的描述嗎? - 在'java.util.concurrent'中可能有一個很好的解決方案。 –
也許我的問題還不清楚,所以我會嘗試以更簡單的方式再次解釋它。我有n個線程和另一個線程x。我想知道一種實現以下行爲的方法:首先執行n個線程,直到出現嚴重代碼行,然後停止執行並進入休眠狀態,然後喚醒x並開始執行,然後x喚醒n個線程並轉至睡眠,然後n個線程再次執行,直到臨界代碼行,停止執行,進入睡眠狀態,再次喚醒x,依此類推。在符號中:n - > x - > n - > x .... –
您可能採取的一種方法是在調用notify all之前讓'OtherRunnable'檢查所有其他線程的狀態。如果'OtherRunnable'看到'MyRunnable'的任何線程都沒有處於等待狀態,則再次進入休眠狀態,直到所有MyRunnable線程處於等待狀態。請參閱[Thread.State](http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Thread.State.html)。 (我沒有發佈這個答案,因爲它對我來說似乎相當不利,但我認爲它應該完成這項工作。) – Tyler