何时唤醒读写器问题中的作者?在释放互斥锁之前还是之后?

Posted

技术标签:

【中文标题】何时唤醒读写器问题中的作者?在释放互斥锁之前还是之后?【英文标题】:When to wake up writer in reader-writer problem? before releasing mutex or after? 【发布时间】:2019-07-14 13:38:19 【问题描述】:

我想知道在我的情况下最好的做法是什么。 在下面的代码中,我在解锁互斥锁之前向作者发出信号

void* Reader(void *context)

    while(TRUE)
    
        LOCK(&g_mutex);
        ++g_activeReaders;
        UNLOCK(&g_mutex);

        printf("reader: %ld counter val: %d ", (long)context, g_counter);

        LOCK(&g_mutex);
        --g_activeReaders;
        printf("g_activeReaders: %d \n", g_activeReaders);
        if(0 == g_activeReaders)
        
            SIGNAL(&g_cv);
        
        UNLOCK(&g_mutex);
    

    return NULL;

我想知道这是否出于某种原因更好,以防止死锁

void* Reader(void *context)

    int signalFlag;
        while(TRUE)
    
                signalFlag = 0;
        LOCK(&g_mutex);
        ++g_activeReaders;
        UNLOCK(&g_mutex);

        printf("reader: %ld counter val: %d ", (long)context, g_counter);

        LOCK(&g_mutex);
        --g_activeReaders;
        printf("g_activeReaders: %d \n", g_activeReaders);
        if(0 == g_activeReaders)
        
                        signalFlag = 1;
        
        UNLOCK(&g_mutex);

                if(signalFlag)
                SIGNAL(&g_cv);
    


    return NULL;

我的完整程序是:

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

pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t g_cv = PTHREAD_COND_INITIALIZER;
int g_activeReaders = 0;
int g_counter;

#define LOCK(X) pthread_mutex_lock(X)
#define UNLOCK(X) pthread_mutex_unlock(X)
#define WAIT pthread_cond_wait
#define WAKE_ALL pthread_cond_broadcast
#define SIGNAL pthread_cond_signal
#define JOIN pthread_join
#define TRUE 1
#define N 3

void* Writer(void * context)

    while(TRUE)
    
        LOCK(&g_mutex);
        while(g_activeReaders)
        
            WAIT(&g_cv, &g_mutex);
        

        ++g_counter;
        UNLOCK(&g_mutex);
    

    return NULL;


void* Reader(void *context)

    while(TRUE)
    
        LOCK(&g_mutex);
        ++g_activeReaders;
        UNLOCK(&g_mutex);

        printf("reader: %ld counter val: %d ", (long)context, g_counter);

        LOCK(&g_mutex);
        --g_activeReaders;
        printf("g_activeReaders: %d \n", g_activeReaders);
        if(0 == g_activeReaders)
        
            SIGNAL(&g_cv);
        
        UNLOCK(&g_mutex);
    

    return NULL;


void InitWriters(pthread_t* writers, int count)

    int status;
    int i;

    for(i = 0; i < count; ++i)
    
        status = pthread_create(&writers[i], NULL, Writer, NULL);

        if(status)
        
            fprintf(stderr, "Writer create fail\n");
            exit(-1);
        
    


void InitReaders(pthread_t* readers, int count)

    int status;
    int i;

    for(i = 0; i < count; ++i)
    
        long e = i;
        status = pthread_create(&readers[i], NULL, Reader, (void*) e);

        if(status)
        
            fprintf(stderr, "readers create fail\n");
            exit(-1);
        
    


void JoinThreads(pthread_t* threads, int count)

    int status;
    int i;

    for(i = 0; i < count; ++i)
    
        status = pthread_join(threads[i], NULL);

        if(status)
        
            fprintf(stderr, "readers create fail\n");
            exit(-1);
        
    


int main(void)

    pthread_t writer;
    pthread_t readers[N];

    InitWriters(&writer, 1);
    InitReaders(readers, N);

    JoinThreads(&writer, 1);
    JoinThreads(readers, N);

    pthread_cond_destroy(&g_cv);
    pthread_mutex_destroy(&g_mutex);

    return 0;


我的实现基于找到的伪代码(此处)[Reader/Writer implementation in C

【问题讨论】:

【参考方案1】:

正确性无关紧要 - 两者都可以,并且没有死锁。

在您使用不同线程优先级的情况下,在解锁互斥锁之前发出条件变量信号的实现可以确保等待条件变量的较高优先级线程将优先获得互斥锁而不是较低优先级的线程- 仅在互斥体上等待的优先级线程。

【讨论】:

感谢您的回答,您能解释一下高优先级获取互斥锁的机制是如何工作的吗? @avish:如果您在仍持有互斥锁的同时发出信号,则等待条件变量的线程之一可以重新排队到互斥锁本身,因此当您解锁互斥锁时,它可以被选中跑步。相反,如果您先解锁互斥锁,则可以选择已经在互斥锁上等待的线程之一在那时运行,并且在发出条件变量信号时,该互斥锁已被另一个线程重新占用。

以上是关于何时唤醒读写器问题中的作者?在释放互斥锁之前还是之后?的主要内容,如果未能解决你的问题,请参考以下文章

操作系统面试题

Java 线程锁机制 -Synchronized Lock 互斥锁 读写锁

再探 同步与互斥

再探 同步与互斥

pthread之读写锁

wait/notify之虚假唤醒