2017-05-23 1 views
0

Angenommen, ich habe einen Code, der beim Zugriff auf einen freigegebenen Zustand einen Mutex enthält. Irgendwann stelle ich fest, dass ich einen neuen Thread erstellen muss und somit pthread_create aufrufen muss, während ich den Mutex immer noch halte. Wird das als sicher angesehen?Ist es sicher, pthread_create mit einem Mutex aufzurufen?

Angenommen, mein gemeinsam genutzter Status ist ein globaler Zähler, der die Anzahl der erfolgreich erstellten Pthreads verfolgt, und ein anderer Thread verwendet diesen Zähler, um die Informationen live auf dem Bildschirm anzuzeigen. Außerdem möchte ich nicht, dass die Anzahl der Pthreads größer als ein bestimmter Maximalwert wird (z. B. 10 für Bestimmtheit). Wenn ich den Zähler inkrementiere und dann den Mutex vor dem Aufruf von pthread_create freigebe, besteht die Möglichkeit, dass pthread_create fehlschlägt, und dann zeigt der Zähler fälschlicherweise mehr Threads (10) als I an.

Nehmen wir an, der Zähler ist derzeit bei 9. tatsächlich erfolgreich erstellt (9).

Wenn ich zuerst den Mutex freigebe, dann rufe pthread_create auf und erhalte dann den Mutex, um den Zähler zu erhöhen, wenn der Aufruf erfolgreich war, dann zwischen dem Freigeben des Mutex und dem Zurückkehren von pthread_create könnte ein anderer Thread habe auch pthread_create aufgerufen und den Zähler inkrementiert (auf 10). So habe ich dann einen 11. Pthread erstellt und der Zähler wird 11. Aber ich sollte nicht mehr als 10 Pthreads erstellt haben.

Es scheint also so, als ob die einzige Möglichkeit, Konsistenz im gemeinsam genutzten Zustand zu garantieren, darin besteht, den Mutex beim Aufruf von pthread_create zu halten. Aber ich bin mir bewusst, dass man im Allgemeinen keinen unbekannten Code anrufen sollte, wenn man einen Mutex hält, also weiß ich nicht, was man in einem solchen Fall tun kann.

EDIT: Hier ist ein Beispielcode, der dieses Problem

#include <stdio.h> 
#include <pthread.h> 
#include <unistd.h> 

void *do_stuff(void *arg); 

int pthreads_counter = 0; 
pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; 

#define MAX_PTHREADS_COUNT 10 

/* Could potentially be called from multiple threads simultaneously */ 
int create_thread_and_increment_counter() 
{ 
    pthread_t thread; 

    if (pthread_mutex_lock(&mtx) != 0) 
     return -1; 

    if (pthreads_counter >= MAX_PTHREADS_COUNT) { 
     pthread_mutex_unlock(&mtx); 
     return -1; 
    } 

    ++pthreads_counter; 

    if (pthread_create(&thread, NULL, do_stuff, NULL) != 0) { 
     --pthreads_counter; 
     pthread_mutex_unlock(&mtx); 
     return -1; 
    } 

    pthread_mutex_unlock(&mtx); 
    return 0; 
} 

void *do_stuff(void *arg) 
{ 
    /* do stuff */ 
    return NULL; 
} 

/* Created somewhere else */ 
void *display_thread(void *arg) 
{ 
    while (1) { 
     if (pthread_mutex_lock(&mtx) != 0) 
      break; 

     printf("%d\n", pthreads_counter); 
     pthread_mutex_unlock(&mtx); 
     usleep(1000000); 
    } 

    return NULL; 
} 

Antwort

1

Es ist in Ordnung pthread_create() zu nennen, während im Besitz einer Mutex haben würde.

Verwandte Themen