Стек Трайбера — различия между версиями

Материал из Викиконспекты
Перейти к: навигация, поиск
(запятые и другие незначительные правки)
Строка 1: Строка 1:
 +
{| class="wikitable" align="center" style="color: red; background-color: black; font-size: 56px; width: 800px;"
 +
|+
 +
|-align="center"
 +
|'''НЕТ ВОЙНЕ'''
 +
|-style="font-size: 16px;"
 +
|
 +
24 февраля 2022 года российское руководство во главе с Владимиром Путиным развязало агрессивную войну против Украины. В глазах всего мира это военное преступление совершено от лица всей страны, всех россиян.
 +
 +
Будучи гражданами Российской Федерации, мы против своей воли оказались ответственными за нарушение международного права, военное вторжение и массовую гибель людей. Чудовищность совершенного преступления не оставляет возможности промолчать или ограничиться пассивным несогласием.
 +
 +
Мы убеждены в абсолютной ценности человеческой жизни, в незыблемости прав и свобод личности. Режим Путина — угроза этим ценностям. Наша задача — обьединить все силы для сопротивления ей.
 +
 +
Эту войну начали не россияне, а обезумевший диктатор. И наш гражданский долг — сделать всё, чтобы её остановить.
 +
 +
''Антивоенный комитет России''
 +
|-style="font-size: 16px;"
 +
|Распространяйте правду о текущих событиях, оберегайте от пропаганды своих друзей и близких. Изменение общественного восприятия войны - ключ к её завершению.
 +
|-style="font-size: 16px;"
 +
|[https://meduza.io/ meduza.io], [https://www.youtube.com/c/popularpolitics/videos Популярная политика], [https://novayagazeta.ru/ Новая газета], [https://zona.media/ zona.media], [https://www.youtube.com/c/MackNack/videos Майкл Наки].
 +
|}
 +
 
{{В разработке}}
 
{{В разработке}}
 
'''Стек Трайбера''' (англ. ''Treiber Stack'') —  масштабируеммый стек без блокировок (англ. ''lock-free''). Считается, что впервые данный алгоритм был опубликовал R. Kent Treiber<ref>[http://domino.research.ibm.com/library/cyberdig.nsf/0/58319a2ed2b1078985257003004617ef?OpenDocument R. Kent Treiber {{---}} Systems Programming: Coping with Parallelism, 1968]</ref>. Алгоритм использует примитив <tex>CAS</tex> (''compare and set'').
 
'''Стек Трайбера''' (англ. ''Treiber Stack'') —  масштабируеммый стек без блокировок (англ. ''lock-free''). Считается, что впервые данный алгоритм был опубликовал R. Kent Treiber<ref>[http://domino.research.ibm.com/library/cyberdig.nsf/0/58319a2ed2b1078985257003004617ef?OpenDocument R. Kent Treiber {{---}} Systems Programming: Coping with Parallelism, 1968]</ref>. Алгоритм использует примитив <tex>CAS</tex> (''compare and set'').

Версия 08:25, 1 сентября 2022

НЕТ ВОЙНЕ

24 февраля 2022 года российское руководство во главе с Владимиром Путиным развязало агрессивную войну против Украины. В глазах всего мира это военное преступление совершено от лица всей страны, всех россиян.

Будучи гражданами Российской Федерации, мы против своей воли оказались ответственными за нарушение международного права, военное вторжение и массовую гибель людей. Чудовищность совершенного преступления не оставляет возможности промолчать или ограничиться пассивным несогласием.

Мы убеждены в абсолютной ценности человеческой жизни, в незыблемости прав и свобод личности. Режим Путина — угроза этим ценностям. Наша задача — обьединить все силы для сопротивления ей.

Эту войну начали не россияне, а обезумевший диктатор. И наш гражданский долг — сделать всё, чтобы её остановить.

Антивоенный комитет России

Распространяйте правду о текущих событиях, оберегайте от пропаганды своих друзей и близких. Изменение общественного восприятия войны - ключ к её завершению.
meduza.io, Популярная политика, Новая газета, zona.media, Майкл Наки.
Эта статья находится в разработке!

Стек Трайбера (англ. Treiber Stack) — масштабируеммый стек без блокировок (англ. lock-free). Считается, что впервые данный алгоритм был опубликовал R. Kent Treiber[1]. Алгоритм использует примитив [math]CAS[/math] (compare and set).

Описание

Требования к алгоритму

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

Lock-free алгоритмы и CAS

Свойство неблокируемости (англ. Lock-freedom) гарантирует прогресс в системе. Для его реализации используется операция [math]CAS[/math].

Определение:
Сравнение с обменом (англ. compare and set, compare and swap, CAS) — атомарная инструкция, сравнивающая значение в памяти с первым аргументом и, в случае успеха, записывающая второй аргумент в память.

Ниже представлен псевдокод операции [math]CAS[/math] для целочисленных переменных.

fun cas(int* p, int old, int new): bool
    if *p != old 
        return false
    *p = new
    return true

[math]CAS[/math] используется для реализации таких примитивов синхронизации, как mutex и semaphore. Это своеобразный базовый "кирпичик" для Lock-free алгоритмов, ведь если [math]CAS[/math] привел к неудаче, то другой поток изменил старое значение. [math]CAS[/math] реализован на уровне атомарных переменных во многих языках программирования.

Алгоритм

Идеи

Переходя от требований к конкретной реализации, введем следующие условия:

  1. Добавлять новый элемент только убедившись, что на момент окончания операции, указатель на голову стека остался тот же. Другими словами, элемент, выбранный нами в качестве [math]next[/math], на момент окончания операции все еще актуален.
  2. При удалении элемента, перед его возвратом, нужно быть уверенным, что мы действительно удаляем текущую голову стека и в качестве новой головы предъявляем [math]H.next[/math].

Структура стека

Как всегда, каждый элемент стека содержит информацию о хранимом значении ([math]value[/math]) и указатель на следующий элемент ([math]next[/math]). Также имеем указатель на голову стека [math]H[/math], который будем изменять при помощи операции [math]CAS[/math]. Если при этом голова указывает на [math]null[/math], то стек — пуст.

Удаление элементов

Запомним, на что указывает голова стека (запишем в локальную переменную [math]head[/math]). Значение, которое хранит в себе [math]head[/math], — то, что необходимо будет вернуть. Попробуем переместить голову стеком [math]CAS[/math]ом. Если удалось — вернем [math]head.value[/math]. Если нет, то это означает, что с момента начала операции стек был изменен. Поэтому попробуем проделать операцию заново.

Добавление элементов

Запомним, куда указывает голова стека (запишем в локальную переменную [math]head[/math]). Создадим новый элемент, который хотим добавить в начало стека. Указатель на следующее значение для него — [math]head[/math]. Попробуем переместить [math]H[/math] на новый элемент, при помощи [math]CAS[/math]. Если это удалось — добавление прошло успешно. Если нет, то кто-то другой изменил стек, пока мы пытались добавить элемент. Придется начинать сначала.

Псевдокод

fun pop(): Int
    while (true) //Cas loop
      head = H
      if (CAS (&H, head, head.next)) 
        return head.value

fun push(x: Int)
    while (true) //Cas loop
      head = H
      if (head == null)
        throw new EmptyStackException();
      newHead = Node {value: x, next: head}
      if (CAS (&H, head, newHead)) 
        return

Примечания

См. также

Источники информации