синхронизация потоков
От: tdiff  
Дата: 28.03.14 14:21
Оценка: 1 (1) :))) :))
Возьмём классический пример синхронизации потоков:


bool flag = false;
void thread_1()
{
    while (!flag) {
        work();
    }
}

void thread_2()
{
    sleep(1000);
    flag = true;
}

В функции work() flag не меняется.

Подобный код приводится в качестве примера ошибочного, т.к. может быть оптимизирован компилятором до

void thread_1_real()
{
    bool f = flag;
    while (!f) {
        work();
    }
}

Такая оптимизация возможна, т.к. компилятор видит, что раз внутри work() flag не меняется, поэтому
нет смысла считывать его на каждой итерации.


Стандартное в практике решение этой проблемы — использовать mutex:
mutex m;
 bool flag = false;

void thread_1_sync()
{
    while (true) {
        {
            scoped_lock lock(m);
            if (flag) break;
        }
        work();
    }
}

void thread_2_sync()
{
    sleep(1000);
    {
        scoped_lock lock(m);
        flag = true;
    }
}


Вопрос: что помешает компилятору и в этом случае оптимизировать чтение значения flag примерно вот так:
void thread_1_sync_real()
{
    bool f;
    scoped_lock lock(m) {
        f = flag;
    }
    while (true) {
        if (f) break;
        work();
    }
}


Моё предположение такое: где-то внутри mutex используется какая-то специальная инструкция типа memory barrier, которую компилятор не может позволить себе отоптимизировать.
Так ли это? Если да, то что это за инструкция на самом деле?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.