Возможно ли использование нескольких производителей для одного потребителя в режиме без блокировки? - PullRequest
9 голосов
/ 28 января 2010

У меня есть куча потоков, которые много общаются друг с другом.Я бы предпочел, чтобы это было без блокировки.

Для каждого потока я хочу иметь почтовый ящик, куда другие потоки могут отправлять ему сообщения (но только владелец может удалять сообщения).Это ситуация с несколькими производителями для одного потребителя.Могу ли я сделать это в условиях без блокировки / высокой производительности?(Это во внутреннем цикле гигантской симуляции.)

Ответы [ 4 ]

10 голосов
/ 30 сентября 2010

Очередь с несколькими потребителями без блокировки (MPSC) без блокировки - это один из самых простых алгоритмов без блокировок для реализации.

Самая базовая реализация требует простой список без блокировок с односвязными связями (SList) только с push () и flush (). Функции доступны в Windows API как InterlockedFlushSList () и InterlockedPushEntrySList (), но их очень легко выполнить самостоятельно.

Несколько элементов Push (), поступающих от производителя, на SList с использованием CAS (блокировка сравнения и обмена).

Single Consumer выполняет flush (), который меняет голову SList на NULL, используя XCHG (обмен с блокировкой). Потребитель затем имеет список предметов в обратном порядке.

Чтобы обработать элементы по порядку, вы должны просто перевернуть список, возвращенный функцией flush (), перед его обработкой. Если вас не волнует порядок, вы можете просто просмотреть список сразу, чтобы обработать его.

Две заметки, если вы катите свои собственные функции:

1) Если вы работаете в системе со слабым упорядочением памяти (например, PowerPC), вам нужно поставить «барьер освобождения памяти» в начале функции push () и «барьер памяти aquire» в конце функция flush ().

2) Вы можете значительно упростить и оптимизировать функции, потому что проблема ABA с SLists возникает во время функции pop (). Вы не можете иметь проблемы ABA с SList, если вы используете только push () и flush (). Это означает, что вы можете реализовать его как единый указатель, очень похожий на код без блокировки, и нет необходимости в счетчике последовательностей для предотвращения ABA.

3 голосов
/ 28 января 2010

Конечно, если у вас есть атомарная CompareAndSwap инструкция:

for (i = 0; ; i = (i + 1) % MAILBOX_SIZE)
{
    if ((mailbox[i].owned == false) &&
        (CompareAndSwap(&mailbox[i].owned, true, false) == false))
        break;
}

mailbox[i].message = message;
mailbox[i].ready = true;

После прочтения сообщения потребительский поток просто устанавливает mailbox[i].ready = false; mailbox[i].owned = false; (в таком порядке).

2 голосов
/ 28 января 2010

Вот статья из Университета Рочестера, иллюстрирующая неблокирующую параллельную очередь . Алгоритм, описанный в статье, демонстрирует один метод создания очереди без блокировки.

0 голосов
/ 28 января 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...