简体   繁体   中英

C - Concurrency Issue

I have a problem with my code developed in C on Linux.

I have a structure like :

typedef struct _my_sem {
    unsigned int valid;
    pthread_mutex_t m;
} my_sem;

and the following functions (error management is NOT reported) :

void my_sem_init(my_sem *s);
void my_sem_destroy(my_sem *s);
void my_sem_lock(my_sem *s);
void my_sem_unlock(my_sem *s);


void my_sem_init(my_sem *s)
{
    pthread_mutex_create(&s->m);
    s->valid = 1;
}

void my_sem_destroy(my_sem *s)
{
    if (s->valid) {
        pthread_mutex_destroy(&s->m);
        s->valid = 0;
    }
}

void my_sem_lock(my_sem *s) {
    if (s->valid)
        pthread_mutex_lock(&s->m);
}

void my_sem_unlock(my_sem *s) {
    if (s->valid)
        pthread_mutex_unlock(&s->m);
}

This code have a problem of concurrency. If someone is trying to lock my_sem and, in the same time someone is destroyng the objcet, the call will fail.

How can I solve this problem of concurrency ?

The design you present has a chicken-and-egg problem: the members my_sem.valid are intended to indicate to multiple threads whether a given mutex is in a valid state, but multiple threads accessing those members produces a data race when one of the accesses is a write, and the accesses are not ordered with respect to each other (such as by protecting access with a mutex).

Moreover, you cannot solve this problem by adjusting the type of valid to one that can be updated atomically, because initialization / finalization of the mutex and update of valid must be performed as an indivisible unit for your functions to work properly. This requires engaging another mutex, a semaphore, or some similar synchronization aid.

You do not solve anything by adding an additional synchronization object to your structure, however, because if you cannot rely on the existing mutex to be in a known state, then neither can you rely on the state of the new object. To rescue this design, therefore, you need a global mutex or semaphore with which the body of each of the four functions is protected.

Here's an alternative: don't hand out uninitialized mutexes, and don't destroy mutexes that are (or may still be) in use. If necessary, you can even use the mutex itself to protect tests of whether it is still in use, provided that you structure your code to avoid any possibility of re-testing the in-use state of any mutex after once finding that mutex not in use. This will require changes to how you use your mutexes, to your mutex management functions, and to your struct (if you retain the struct at all).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM