2014-01-02 3 views
1

pEnd_ является членом объекта и может увеличиваться только в add(), как показано ниже в одном потоке, его можно прочитать другим потоком. Нужно ли нам __sync_synchronize в add()?Здесь необходим барьер памяти * * pEnd_ = v; __sync_synchronize(); ++ pEnd_; "?

struct Vector { 
    ... 
    void add(int v) { 
     *pEnd_ = v; 
     __sync_synchronize(); // is this needed? 
     ++pEnd_; 
    } 
private: 
    int* pBegin_; 
    int* pEnd_; 
} 

итерация в другой теме.

for (p = pBegin_; p != pEnd_; ++p) { 
    // read barrier here may be inserted 
    if (*p) { 
    .... 
    } 
} 
+0

По барьерам вы имеете в виду «мьютекс»? или "sync_synchronize"? – ChronoTrigger

+0

sync_synchronize – poordeveloper

+1

У вас есть условие гонки, если несколько потоков выполняют '++ pEnd_' в одно и то же время. – ChronoTrigger

ответ

3

по крайней мере без барьера памяти выпуска, модификация, внесенная в *pEnd не обязательно видимая для других потоков. Так что что-то нужно.

Строго говоря, нет, __sync_synchronize() не требуется, поскольку это полный барьер памяти. Если ваш компилятор не имеет встроенного барьера (иначе говоря, «барьера записи»), полный барьер является разумным.

На первый взгляд, существует гонка данных, вызванная тем фактом, что ваш приращение pEnd не влияет на чтение из других потоков. Отдельные платформы могут гарантировать, что доступ к атомам будет равен int*, а также может гарантировать, что изменения станут видимыми в других потоках в том же порядке, в котором они были записаны в этом потоке. Так что на некоторых платформах код в порядке (и полный барьер препятствует перезаписи записей). Ни один из них не является стандартным C++, и он может быть специфичным для аппаратного обеспечения, а не для компилятора.

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

  • Нет связанных вопросов^_^