Использование fetch-and-add в качестве блокировки - PullRequest
0 голосов
/ 27 февраля 2020

Я пытаюсь понять, как fetch-and-add можно использовать как блокировку. Вот что написано в книге (ОС: 3 штуки):

Операция basi c довольно проста: когда поток хочет получить блокировку, он сначала выполняет атоми c получить и добавить на стоимость билета; это значение теперь считается поворотом потока (myturn). Затем глобально разделяемый lock-> turn используется, чтобы определить, в каком повороте потока он находится; когда (myturn == turn) для данного потока, это очередь этого потока, чтобы войти в критическую секцию.

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

Другая часть гласит:

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

То, что я не могу интерпретировать так, чтобы проверки не проводились, что не может быть правдой, потому что это сводит на нет всю совокупность блокировок срезов. Что я здесь снимаю? Спасибо.

1 Ответ

2 голосов
/ 27 февраля 2020

Что я не понимаю, так это то, как поток проверяет, удерживается ли блокировка другим процессом, прежде чем войти в критическое видение.

Для этого вам понадобится "atomi c fetch" , может быть что-то вроде "while( atomic_fetch(currently_serving) != my_ticket) { /* wait */ }".

Если у вас есть "atomi c fetch and add", то вы можете реализовать "atomi c fetch", выполнив "atomi c fetch and add значение ноль ", может быть что-то вроде" while( atomic_fetch_and_add(currently_serving, 0) != my_ticket) { /* wait */ } ".

Для справки; полная последовательность может выглядеть примерно так:

    my_ticket = atomic_fetch_and_add(ticket_counter, 1);

    while( atomic_fetch_and_add(currently_serving, 0) != my_ticket) {
        /* wait */
    }

    /* Critical section (lock successfully acquired). */

    atomic_fetch_and_add(currently_serving, 1);   /* Release the lock */

Конечно, у вас может быть лучшая выборка atomi c, которую вы можете использовать вместо этого (например, для некоторых процессоров любая нормальная выровненная загрузка - это atomi c).

...