пусто при синхронизации в с ++? - PullRequest
3 голосов
/ 19 апреля 2011
static char szInfo[256];
static volatile bool bIsLocked = false;

static void ApiFunc() {
    while (bIsLocked) { }
    bIsLocked = true;
    //do something to szInfo
    bIsLocked = false;
}

Прошло некоторое время с тех пор, как я выполнил какую-либо многопоточность в C ++. Это достаточно безопасно? Для меня это намного более простое решение, чем использование мьютекса, но зачем мне вместо этого использовать мьютекс Windows?

Ответы [ 6 ]

6 голосов
/ 19 апреля 2011

Вы бы использовали мьютекс (или, скорее, критический раздел), потому что это сработало бы. Этот код не синхронизируется. Несколько потоков могут войти в критическую область.

И, конечно же, настоящие замки не вращаются. Что ж, спин-блокировки делают, но вам нужно глубокое понимание влияния спин-блокировки на производительность, прежде чем использовать ее.

2 голосов
/ 19 апреля 2011

То, что вы реализовали, это почти Алгоритм Петерсона . Как указывалось выше, это не безопасно для потоков, так как не существует механизма, предотвращающего одновременное попадание обоих потоков в критическую секцию. Вы можете попытаться правильно реализовать алгоритм Петерсона, но гораздо эффективнее использовать настоящий мьютекс.

Основная проблема вашего подхода заключается в том, что поток может быть прерван после выхода из цикла while, но до того, как он установит для bool значение true. Если это произойдет, то ваши два потока вместе войдут в критический раздел. Если у вас более двух потоков, то у вас будет несколько потоков, которые одновременно выходят из цикла.

2 голосов
/ 19 апреля 2011

Это не потокобезопасность вообще!

Поток № 1 получает проверку через желоб, но не устанавливает логическое значение.В это время в критическую сессию приходит поток № 2.

1 голос
/ 19 апреля 2011

Этот код не будет работать так, как вы надеетесь. Между концом цикла while и тем, что вы установили значение true, возникает состояние гонки. Кроме того, процессор занят ожиданием блокировки, в то время как примитивы синхронизации могут выдавать процессор во время ожидания.

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

1 голос
/ 19 апреля 2011

Это совсем не безопасно.volatile не имеет определенной семантики в отношении потоков.Самое большее, это предотвратит полное подавление компилятором назначений (так как их чистый эффект не работает), но не помешает компилятору переупорядочить доступы к szInfo вокруг доступа к bIsLocked, и не будетне позволяйте оборудованию переупорядочивать то, что происходит, или даже полностью подавлять bIsLocked = true.

0 голосов
/ 20 апреля 2011

Использовать замки.

Доклад об опасностях потоков без блокировок, от BoostCon 2010: http://blip.tv/file/4211197/

слайды, примечания, по адресу: http://boostcon.boost.org/2010-resources

...