C - Выходной поток должен обновляться, когда другие потоки изменяют значения - PullRequest
1 голос
/ 09 января 2020

У меня есть программа, которая выполняет некоторые вычисления с использованием многопоточности и добавляет результат в глобальную переменную. Существует также счетчик того, сколько потоков уже завершено и сколько еще работает. Нити оторваны. В дополнение к этим потокам есть выходной поток, который распознает, изменил ли другой поток одну из этих глобальных переменных. Если так, то он их напечатает. Выходной поток также ожидает пассивный.

Как заставить выходной поток ожидать изменения глобальных значений? Я мог бы сделать некоторое время l oop, пока все потоки не закончат и наблюдать за изменением значений, но это не совсем то, чего я хочу. Я хочу, чтобы поток вывода ожидал пассивно.

sem_t sem;
int val1 = 0;
int val2 = 0;
int active = 0;
int finish = 0;

void* calc(void* arg){
    sem_wait(&sem);
    calculate(arg);
    ++finish;
    sem_post(&sem);

    return NULL;
}

void* out(void* arg){

    //what to do here?

    printf();
    return NULL;
}

int main(int argc, char* argv[]){
    pthread_t calcThread;
    int somevalue;
    sem_init(&sem, 0, argv[1]); // max amount of threads running simultaniously
    for(int i = 2; i != argc; i++){
        somevalue = atoi(argv[i]);
        pthread_create(&calcThread, NULL, calc, &somevalue))
        pthread_detach(calcThread);
    }
}

Ответы [ 2 ]

1 голос
/ 09 января 2020

Чтобы достигнуть поведения пассивного ожидания с использованием семафоров, вам нужно 2 переменные семафора вместо одной. Один для контроля чтения и один для контроля над письмом. Давайте назовем их:

sem_t read, write;

Внутри функции calc вам нужно дождаться снятия блокировки чтения. sem_wait(&read); и при выходе из функции calc вам необходимо снять блокировку записи sem_post(&write);, подробнее об этом позже.

В функции out у вас будет обратный подход, вы получите дождитесь снятия блокировки записи sem_wait(&write); и в конце вы снимите блокировку чтения sem_post(&read);

Теперь в main вам нужно будет инициализировать оба семафора:

sem_init(&read, 0, 1);
sem_init(&write, 0, 0);

Обратите внимание, что я инициализировал read значением 1 и write значением 0. Причина в том, что sem_wait проверит значение семафора, если оно больше 0, оно уменьшит значение и продолжит обработка. Поскольку мы хотим, чтобы функция calc выполнялась до функции out, мы инициализируем переменную read 1, чтобы она не ожидала первого нажатия и просто продолжала обработку.

Принимая во внимание, что в функции out нам необходимо присвоить первые значения, прежде чем мы сможем их распечатать / обработать. Поэтому переменная write инициализируется 0 и будет ждать, пока функция calc не завершит sh и не увеличит write с 0 до 1, вызвав sem_post(&write);

Вы можете инициализировать переменную read с количеством создаваемых потоков, но в этом случае возникнет гоночная ситуация, и данные могут быть перезаписаны до того, как функция out обработает их. Чтобы преодолеть эту ситуацию, вам нужно создать буфер для таких значений, как список или массив. Также дополнительный семафор для управления mutexlock, который будет вызываться после каждого sem_wait() и перед каждым sem_post(), чтобы не получить доступ к буферу значений одновременно.

Подробный пример с семафорами можно найти здесь

0 голосов
/ 10 января 2020

предложить:

использовать мьютекс или два

  1. , генерировать pthread_mutex_t mutexName;, который каждый поток использует, чтобы избежать условий гонки при обновлении / доступе к счетчику и другим критическим данным
  2. поток 'display' блокирует pthread_cond_t condName;, вызывая: pthread_cond_wait( condName );.
  3. каждый раз, когда поток обновляет счетчик, он вызывает pthread_cond_signal( condName ), что заставляет поток 'display' продолжить обработку. Когда поток 'display' завершает обработку, он снова блокирует 'pthread_cond'
  4. . Настоятельно рекомендуется прочитать: pthread_cond

Примечание: из-за различной синхронизации Из соображений, данные, к которым осуществляется доступ, должны представлять собой кольцевую очередь, поэтому обновления данных не будут «потеряны»

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...