首页 > 解决方案 > 提出一个用于原子访问共享内存的包装器

问题描述

我在这里与多线程概念作斗争。

有两个线程访问共享结构。想法是先ThreadTwo获取锁并设置data为true,然后运行......如果设置为,ThreadOne则进入睡眠状态,并在设置为后发出信号后唤醒。datatruedatafalse

我所看到的情况:ThreadOne进入睡眠状态,并且在ThreadTwodisables之后data,两个线程似乎都处于死锁状态,或者更确切地说它们被卡住了。

我的理解是:我在结束时解锁互斥锁AccessShm(shmInfo, GET),并且我认为pthread_cond_signal需要已经获得锁,因为它在睡觉前解锁,并且一旦从 发出信号ThreadTwoThreadOne醒来,获取锁,并尝试再次获取内部AccessShm但可以不是因为它已经被收购,所以挂起?

typedef enum
{
    SET,
    GET
} Task;

typedef struct
{
    volatile bool data;     
    pthread_mutex_t pMutex;
    pthread_cond_t cv;
} ShmInfo;

bool AccessShm(ShmInfo *pShm, Task t, ...)  
{
    va_list args;
    bool setValue = true;
    bool retValue = true;

    va_start(args, t);

    pthread_mutex_lock(&pShm->pMutex);

    switch (t)
    {
        case SET:
            setValue = va_arg(args, bool);  
            pShm->data = setValue;
        
            if (setValue == false)
            {
                pthread_cond_signal(&pShm->cv); // wake up only when pShm->data is disabled
            }
            break;
        
        case GET:
            retValue = pShm->data;
            break;

        default:
            break;
    }
    pthread_mutex_unlock(&pShm->pMutex);
    return retValue;
}

void ThreadOne(void *arg)
{
    ShmInfo *shmInfo = (ShmInfo *) arg;
    while(1)
    {
        while(AccessShm(shmInfo, GET) == true) 
        {
          pthread_cond_wait(&shmInfo->cv, &shmInfo->pMutex); 
        }
        // ...
    }
}

void ThreadTwo(void *arg)
{
    ShmInfo *shmInfo = (ShmInfo *) arg;
    // ...
    AccessShm(shmInfo, SET, true);
    
    // some work/delay
    AccessShm(shmInfo, SET, false);
}

标签: cmultithreadingpthreadslocking

解决方案


在调用之前,您没有锁定与条件变量关联的互斥锁pthread_cond_wait()

只能pthread_cond_wait()在关联互斥锁锁定的情况下调用。

根据POSIXpthread_cond_wait()文档(我的粗体字):

pthread_cond_timedwait()andpthread_cond_wait()函数应阻塞条件变量。应用程序应确保这些函数被mutex调用线程锁定调用;否则,将导致错误(对于 PTHREAD_MUTEX_ERRORCHECK 和健壮的互斥锁)或未定义的行为(对于其他互斥锁)。

...


推荐阅读