2013-10-27 3 views
0

У меня есть этот код, здесь нужно синхронизировать использование глобальной переменной c? Возможно ли, что потоки начнут работать в одно и то же время, и один поток перезапишет результат другого потока и в итоге получит либо 2, либо 7?Необходимо синхронизировать использование глобальной переменной

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

int c = 0; 

void* write(void*) 
{ 
    c += 2; 
} 

void* read(void*) 
{ 
    c += 7; 
} 

int main() 
{ 
    pthread_t t1; 
    pthread_t t2; 

    std::cout << "first C = " << c << std::endl; 
    int r1 = pthread_create(&t1, 0, &write, 0); 
    int r2 = pthread_create(&t2, 0, &read, 0); 
    pthread_join(t1, 0); 
    pthread_join(t2, 0); 
    std::cout << " C = " << c << std::endl; 

    return 0; 
} 
+2

Вы знакомы с мьютексами и блокировкой? Редактировать: Это классическая проблема читателей-писателей: http://en.wikipedia.org/wiki/Readers%E2%80%93writers_problem – AndyG

+0

Да, я знаком с мьютексами, спасибо за URL. –

ответ

1

Да, вам необходимо защитить доступ к глобальной переменной. Вам нужно либо использовать mutex, либо вам нужно использовать тип atomic (включая операции атомирования для их изменения).

Если вы этого не сделаете, проблема в том, что нормальный += требует операции чтения, добавляет некоторое значение и затем записывает результат обратно в память. Если два потока выполняют это одновременно, они могут перекрываться, например, оба будут читать 0 в вашем примере кода, тогда оба записывают их результат, который означает, что выигрывает последняя операция записи, и, следовательно, другое добавление теряется. В итоге вы получите 2 или 7 вместо 9, как вы уже подозревали.

1

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

То есть, вам необходимо получить доступ к c, используя соответствующую синхронизацию.

0

В машинах SMP (с отдельными памятью данных) есть еще одна увлекательная вещь, которая представляет собой синхронизацию между потоками. Если потоки выполняются в разных ядрах/процессорах, даже если оба потока, обновляющие c, не работают ровно в одно и то же время, они могут не увидеть обновление памяти из другого потока немедленно. Например, используя синхронизацию pthread_mutex_t, вы позаботитесь об этой проблеме.

Обратите внимание, что pthread_join() синхронизирует память с другими потоками, поэтому дополнительные меры не нужны после присоединения ваших потоков, чтобы гарантировать, что c видно с его обновленным значением.

Вот список функций потока POSIX, которые гарантируют синхронизацию памяти с другими потоками: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_11.

Смежные вопросы