Лучший способ синхронизировать доступ к общей памяти для сценария с одним писателем и несколькими читателями? - PullRequest
0 голосов
/ 29 января 2019

У меня есть несколько процессов, которые могут получить доступ к блоку общей памяти.Только один процесс будет время от времени записывать в общую память, несколько других процессов могут время от времени читать из общей памяти.Я не хочу реализовывать следующий сценарий:

  1. читатель должен ждать, пока писатель не пишет, прежде чем он прочитает из общей памяти;
  2. писатель должен ждать, пока не будет читателячитает перед записью в общую память;
  3. считыватели могут читать из общей памяти одновременно.

Я пытался использовать процесс общего мьютекса и флаги в общей памяти для реализации этого сценария.(разделяемый мьютекс процесса используется для защиты флага):

  1. , когда писатель хочет выполнить запись в общую память: дождитесь, пока флаг читателя не станет равным 0 -> установите флаг писателя в 1 ->запись в разделяемую память -> установить флаг записи на 0
  2. , когда считыватель хочет прочитать из общей памяти: подождите, пока флаг записи не станет 0 -> увеличить флаг читателя -> читать из общей памяти -> уменьшить флаг читателя

Код выглядит следующим образом:

typedef struct {
    pthread_mutex_t rw_mutex;
    int read_flag;
    int write_flag;
} shared_data_t;
void read_start(shared_data_t *p_data)
{   
    while (1)
    {   
        pthread_mutex_lock(&p_data->rw_mutex);
        if (p_data->write_flag <= 0)
        {   
            p_data->read_flag++;
            pthread_mutex_unlock(&p_data->rw_mutex);
            break;
        }
        else
        {
            pthread_mutex_unlock(&p_data->rw_mutex);
            usleep(1);
        }
    }
}

void read_finish(shared_data_t *p_data)
{
    pthread_mutex_lock(&p_data->rw_mutex);
    p_data->read_flag--;
    pthread_mutex_unlock(&p_data->rw_mutex);
}

void write_start(shared_data_t *p_data)
{
    while (1)
    {
        pthread_mutex_lock(&p_data->rw_mutex);
        if (p_data->read_flag <= 0)
        {
            printf("set write flag to 1\n");
            p_data->write_flag = 1;
            pthread_mutex_unlock(&p_data->rw_mutex);
            break;
        }
        else
        {
            pthread_mutex_unlock(&p_data->rw_mutex);
            usleep(1);
        }
    }
}

void write_finish(shared_data_t *p_data)
{
    pthread_mutex_lock(&p_data->rw_mutex);
    p_data->write_flag = 0;
    pthread_mutex_unlock(&p_data->rw_mutex);
}

Процесс записи писателя выглядит так:

write_start(p_data);
//write data
write_finish(p_data);

Процесс чтения читателя выглядит следующим образом:

read_start(p_data);
//read data
read_finish(p_data);

Код работает, но я не проверял, есть ли потенциальные ошибки.

Я думаю, что должен быть какой-то лучший способ реализовать этот сценарий.Любое предложение приветствуется!

EDIT1: Я попытался использовать сигнал условия, чтобы заменить использование usleep, и код выглядит помет лучше.

typedef struct {
    pthread_mutex_t rw_mutex;
    pthread_cond_t rw_cond;
    int read_flag;
    int write_flag;
} shared_data_t;

void read_start(shared_data_t *p_data)
{   
    while (1)
    {   
        pthread_mutex_lock(&p_data->rw_mutex);
        if (p_data->write_flag <= 0)
        {
            p_data->read_flag++;
            pthread_mutex_unlock(&p_data->rw_mutex);
            break;
        }
        else
        {
            pthread_cond_wait(&p_data->rw_cond, &p_data->rw_mutex);
            pthread_mutex_unlock(&p_data->rw_mutex);
        }
    }
}

void read_finish(shared_data_t *p_data)
{
    pthread_mutex_lock(&p_data->rw_mutex);
    p_data->read_flag--;
    pthread_cond_broadcast(&p_data->rw_cond);
    pthread_mutex_unlock(&p_data->rw_mutex);
}

void write_start(shared_data_t *p_data)
{
    while (1)
    {
        pthread_mutex_lock(&p_data->rw_mutex);
        if (p_data->read_flag <= 0 && p_data->write_flag <= 0)
        {
            printf("set write flag to 1\n");
            p_data->write_flag = 1;
            pthread_mutex_unlock(&p_data->rw_mutex);
            break;
        }
        else
        {
            pthread_cond_wait(&p_data->rw_cond, &p_data->rw_mutex);
            pthread_mutex_unlock(&p_data->rw_mutex);
        }
    }
}

void write_finish(shared_data_t *p_data)
{
    pthread_mutex_lock(&p_data->rw_mutex);
    p_data->write_flag = 0;
    pthread_cond_broadcast(&p_data->rw_cond);
    pthread_mutex_unlock(&p_data->rw_mutex);
}
...