Требуется ли барьер памяти, если второй поток ожидает завершения первого? - PullRequest
0 голосов
/ 10 февраля 2012

Предположим, что поток Alpha записывает в переменную A без блокировки.Второй поток Beta ожидает завершения Alpha, а затем читает переменную A.

Возможно ли, что содержимое A не будет свежим?Может ли запись в память быть отложена сверх срока жизни потока?Разве стандартный механизм ожидания завершения потока Alpha неявно не работает как барьер памяти?

ОБНОВЛЕНИЕ 1

Есть ли примеры ожидания, которые невключить барьер памяти?

Ответы [ 3 ]

4 голосов
/ 10 февраля 2012

Почти наверняка (API, используемый для ожидания завершения потока, должен будет использовать барьеры памяти для своих собственных целей), но я думаю, что для окончательного ответа вам нужно будет поговорить об используемом API конкретного потока.

Например, posix дает такую ​​гарантию на pthread_join(): https://stackoverflow.com/a/3208140/12711

И Win32 документирует, что API-интерфейсы синхронизации для ожидания на объекте (например, дескриптор потока) накладывают барьеры памяти: http://msdn.microsoft.com/en-us/library/ms686355.aspx

2 голосов
/ 10 февраля 2012

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

0 голосов
/ 10 февраля 2012

(Предполагается, что вы имеете в виду C #.)

Если вы имеете в виду Thread буквально, то ваш ответ зависит от того, генерирует ли Thread.Join неявно ли барьеры памяти (что, согласноответы, которые уже даны, вероятно, так и есть).

Однако, если вы имеете в виду, что Alpha и Beta - это пользовательские задачи, выполняемые в фоновом потоке (возможно, из пула потоков), и что «ожидание »относится к синхронизации на уровне пользователя между двумя задачами , тогда более вероятно, что данные будут не свежими, если только не введена сигнальная конструкция или явный барьер.

Вот тривиальный пример:

public class Program
{
    static string A = "foo";
    static volatile bool isAlphaReady = false;

    static void Alpha()
    {
        A = "bar";
        isAlphaReady = true;
    }

    static void Beta()
    {
        while (!isAlphaReady)
            ;   // Wait by polling
        Console.WriteLine(A);
    }

    static void Main(string[] args)
    {
        new Thread(Alpha).Start();
        new Thread(Beta).Start();
        Console.ReadKey();
    }
}

Хотя (интуитивно) кажется, что Beta всегда будет выводить "bar" как значение A, это не гарантируется на многопроцессорном компьютересистема со слабым поведением синхронизации (например, Itanium), в этом случае вместо нее может выводиться "foo".

...