2011-11-30 21 views
8

OS to Linux działający z pthreadspthreads, skąd mam wiedzieć, że inny wątek w procesie nie czeka?

Mam dwa wątki robocze, które działają wiecznie, dopóki zmienna stop nie przyjmie wartości true, a wątki zakończą się z gracją. Zamiast wykonywania oczekującego połączenia oba wątki wywołują pthread_cond_wait, dopóki sygnał nie powiadomi o nowym zadaniu. System działa dobrze.

Należy utworzyć wątek "info", który wyświetli niektóre informacje dotyczące debugowania. Wątek informacyjny będzie próbował czytać i drukować informacje co 30 sekund. Część tych informacji, chciałbym być STANEM każdego wątku roboczego. Czy można znaleźć, czy wątek jest zablokowany w "pthread_cond_wait"? Jeśli wątek czeka jest pthread_cond_wait to STAN == czekanie w dalszym ciągu na stan STATE ==.

while ((sharedvaluffer == 0) && (doneflag == 0)) { 
      pthread_cond_wait (&taks_added, &buffer); 
     }  

Oczywiście możemy zrobić, że więcej kodu. Do powyższego fragmentu możemy dodać zmienną globalną, która oznacza, że ​​wątek jest zablokowany. Kod można wykonać:

while ((sharedvaluffer == 0) && (doneflag == 0)) { 
       lock; 
       i_am_waiting = truel 
       unlock 
       pthread_cond_wait (&taks_added, &buffer); 
} 

Pytanie brzmi, czy istnieje łatwiejszy sposób na bardziej skalowalny. Stos wątku oczekujących jest

Thread 6 (Thread 0x40800940 (LWP 20732)): 
#0 0x00002ba4567a9326 in [email protected]@GLIBC_2.3.2() 
#1 0x00000000007ce2ed in worker(void*)() 
#2 0x00002ba4567a5193 in start_thread() from /lib64/libpthread.so.0 
#3 0x00002ba458a82f0d in clone() from /lib64/libc.so.6 

Odpowiedz

0

Możesz użyć zwrot pthread_self() jako identyfikatora własności mutex. Przechowuj i porównuj. Ponieważ muteks może zostać pobrany przez pojedynczy wątek naraz, będziesz wiedział, który wątek działa (nie czeka), a który nie.

+1

która nie działa, jeśli pracownik blokuje niektóre muteksy (tj. W przypadku wspólnej muteks) – cateof

+0

Dlaczego nie? Każdy wątek ma swój własny identyfikator. Zachowaj dostępny 'pthread_t current_owner' i aktualizuj go za każdym razem, gdy wątek roboczy nabywa muteks. Twój wątek informacyjny porównuje tę zmienną z identyfikatorem każdego wątku roboczego. Pamiętaj, że pthread_t jest 'int' na Linuksie, ale ogólnie jest strukturą w innych systemach, więc nie możesz polegać na atomowości, wymagającej dodatkowej blokady. – jweyrich

0

Prawdopodobnie używasz muteksu który jest zamknięty, gdy warunek zostanie powiadomiony, jeśli tak, to w swoim wątku informacyjnym, po prostu spróbuj blokujący, który mutex - jeśli go nabyć, dobrze jest możliwe, że w czasie próbkowania wątek czeka, w przeciwnym razie, jeśli blokowałoby się, wtedy wiesz, że wątek robi to, co jest (tj. przejął to muteks, co oznacza, że ​​jest w sekcji krytycznej)

+1

to zakłóciłoby wątki. – akappa

+0

odpowiedź Nima jest dobra. Przeciwnie. Używanie trylok dla muteksa oznacza, że ​​po sukcesie drugi wątek śpi.Problem z rozwiązaniem polega na tym, że mutex_ może być współużytkowany przez oba wątki robocze: – cateof

+0

@akappa, dlaczego? jest to próba próby, jeśli się nie uda, w porządku, wątek jest zajęty, jeśli mu się to uda, natychmiast go zwolnisz, ale wiesz, że wątek był w tym momencie w stanie uśpienia. Jakie są minusy? w tym drugim przypadku masz dodatkowy blokadę/odblokowanie na muteksie, na który drugi wątek jest zmuszony czekać - chyba że jest to jakaś krytyczna aplikacja w czasie rzeczywistym, nie uważam tego za problem!?! – Nim

1

Można zarejestrować wspólną strukturę ów w mutex z pthread_mutexattr_getpshared, gdzie każdy wątek rejestruje swój stan (działa, nie działa) przy pomocy pthread_self().

Przed sprawdzeniem zmiennej warunku można ustawić wartość s[pthread_self()]->state = WAITING, a po sprawdzeniu można ustawić wartość s[pthread_self()]->state = WORKING.

Pamiętaj, aby zaprojektować konstrukcję, tak aby nie wystąpił żaden wyścig.

1

Poszedłbym prostą trasą i po prostu włączono wyliczenie stanu na wątek. Przed każdą zmianą stanu pojęciowego zmieniłbyś stan.

void worker(void* parm) 
{ 
    threadstate_t *state = (threadstate_t*)parm; 

    /* ... */ 
    while (...) { 
     state->current = STATE_WORKING; 

     /* ... */ 

     state->current = STATE_WAITING; 
     /* res = pthread_cond_wait(cond, mutex); */ 
    } 
} 

Następnie w wątku interrogration:

void worker_dbg(void* parm) 
{ 
    threadstate_t *states = (threadstate_t*)parm; 
    int i; 

    while (run) { 
     for (i = 0; i < NWORKERS; ++i) { 
      /* _state is a map of states to strings */ 
      printf("Thread %d: %s\n", states[i].id, _state[states[i].current]); 
     } 
     sleep(30); 
    } 
} 

Jeśli off przez 30 sekund, ponieważ stan został zaktualizowany prawo po wydrukowany, to naprawdę nie ma znaczenia. Nie musisz blokować stanu, ponieważ piszesz tylko od właściciela i czytasz tylko z wątku debugowania.

+1

Główna zasada jest podobna do mojej, ale przywiązujesz stan do wątków, podczas gdy ja robię to na muteksach, więc Twoje podejście jest czystsze niż moje. +1 – akappa

+0

Możesz podejść i rzucić to w moje, dodając po prostu każdy muteks do wyliczenia stanu. Tak szczegółowy, jak tego potrzebujesz. – user7116

Powiązane problemy