2009-04-08 18 views
1

Ich möchte einen Thread anhalten, bis ein anderer Thread die Initialisierung beendet hat, ohne pthread_join zu verwenden. Ich habe versucht, einen Join zu verwenden, aber es führt zu einem Deadlock aufgrund eines asynchronen Inter-Thread-Kommunikationssystems, das wir haben. Momentan verwende ich eine (benutzerdefinierte) Sperre, um dies zu erreichen.Warten, bis pthread_create fertig ist, ohne pthread_join zu verwenden

In Gewinde 1:

lock_OfflineWorker.Lock() 
if (pthread_create(&tid0, NULL, RunOfflineWorker, NULL) != 0) 
{ 
} 

lock_OfflineWorker.TryLock(); 
lock_OfflineWorker.Unlock(); 

In Thread 2:

bool OfflineWorker::Initialize() 
{ 
    lock_OfflineWorker.Unlock(); 
} 

Aber das ist unelegant und ich bin nicht sicher, ob die Nebenwirkungen (die Möglichkeit für eine andere Sackgasse). Ist das Ok? Wenn nicht, gibt es eine andere Möglichkeit, dies zu erreichen (Schlösser mit oder aus anderen Gründen)

EDIT: Vergessen ist die „RunOfflineWorker“ -Funktion

void* RunOfflineWorker(void* pData) 
{ 
    g_OfflineWorker.Initialize(); 
} 
+0

Der OfflineWorker führt die Initialisierung durch und fährt dann mit einer anderen Arbeit fort, habe ich recht? – jpalecek

+0

Ja. Unten in der eigentlichen Funktion gibt es eine Rendite.Es führt einige Herzschlag-Operationen (Bibliotheksfunktionen) aus, führt aber keine schweren Operationen durch. – Gayan

+0

Sie können einen Pthread-Mutex nicht aus einem anderen Thread (portabel) entsperren, zu dem Sie ihn gesperrt haben. Siehe http://opengroup.org/onlinepubs/007908775/xsh/pthread_mutex_lock.html. Verwenden Sie die unten angegebenen Bedingungsvariablen. – Doug

Antwort

7

Sie eine Pthread Bedingung verwenden können, warten, bis der Job die erreicht gewollter Staat.

Der Thread1 wartet mit pthread_cond_wait() und der Thread2 signalisiert es mit pthread_cond_signal().

Sie benötigen:

bool   condition ; // or anything else to be tested 
pthread_mutex_t mutex ; 
pthread_cond_t cond ; 

Der erste Thread inits alle:

condition = false ; 
pthread_mutex_init(&mutex , PTHREAD_MUTEX_INITIALIZER); 
pthread_cond_init(&cond , PTHREAD_COND_INITIALIZER); 

Dann wartet es mit dem Mutex gesperrt. In der Regel legen Sie die Wartezeit in eine Schleife, um den Zustand zu überprüfen, was auch immer es ist.

pthread_mutex_lock(&mutex); 
while(! condition) 
{ 
    pthread_cond_wait(&cond , &mutex); 
} 
pthread_mutex_unlock(&mutex); 

Der andere Thread tut dies, wenn angebracht:

pthread_mutex_lock(&mutex); 
condition = true ; // or false ... 
pthread_cond_signal(&cond); 
pthread_mutex_unlock(&mutex); 
+0

Außer Sie haben vergessen, Code für den Mutex – jpalecek

+0

enthalten, ich habe das System mit einem Pthread-Zustand zu arbeiten. Ich habe keine While-Schleife benutzt, nur Warte auf die Bedingung. Sollte ich den Mutex vor dem Aufruf von pthread_cond_wait sperren? Kann pthread_cond_wait den angegebenen Mutex nicht automatisch sperren und entsperren? – Gayan

+0

ok, ich habe die init hinzugefügt. Die Schleife ist da, um zu überprüfen, dass die Bedingung wirklich erfüllt ist, wie Thread 2 auch verwenden kann: condition = false; pthread_cond_signal (cond); Ja, Sie müssen es zuvor sperren, da pthread_cond_wait es entsperrt. –

1

Ich denke, Ihre Lösung ganz gut ist, mit der Ausnahme, dass Sie lock_OfflineWorker.Lock() statt lock_OfflineWorker.TryLock() in Thread verwenden, müssen 1 - mit TryLock(), es doesn tatsächlich Warte auf nichts. Sie können dafür keinen Mutex verwenden, da er von demselben Thread freigegeben werden muss, der ihn gesperrt hat, aber z. eine Semaphor-basierte Sperre würde ausreichen. Die Verwendung eines Monitors (dh Mutex + Condvar) wäre nur komplexer.

Über Deadlocks: Deadlocks sind unmöglich, wenn der Initialisierungsteil von OfflineWorker (dh der Code, bevor es die Sperre freigibt) nicht irgendwo wartet. Wenn es tatsächlich Deadlocks mit Ihrer Lösung gibt, würde jede andere Lösung, die Thread 1 auf Thread 2 warten lässt, auch diese haben (ich kann mir eine solche Situation vorstellen).

Nach dem Kommentar bearbeiten: Wenn Sie Nachrichten an Thread 1 übergeben, während die Initialisierung von Thread 2 abgeschlossen ist, besteht die Möglichkeit eines Deadlocks, insbesondere wenn ein begrenzter Puffer für Nachrichten vorhanden ist oder wenn die Nachrichtenübergabe funktioniert wartet auf Antwort. In dieser Situation würde ich vorschlagen, einfach auf die Idee zu verzichten, auf Thread 2 zu warten und vielleicht einen Callback zu übergeben, der von Thread 2 aufgerufen wird, wenn die Initialisierung beendet ist.

+0

Ich habe den Code hier sehr abgekürzt. Es gibt Funktionen, die Nachrichten an Thread 1 weiterleiten, aber wie Sie bereits sagten, sollten diese keine Deadlocks verursachen. Ich werde das untersuchen. Vielen Dank – Gayan

Verwandte Themen