Как избежать тупиков? - PullRequest
30 голосов
/ 29 июня 2009

При использовании нескольких потоков разделяемая память должна быть заблокирована критическими секциями. Однако использование критических секций приводит к потенциальным взаимоблокировкам Как их можно избежать?

Ответы [ 8 ]

10 голосов
/ 29 июня 2009

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

5 голосов
/ 29 июня 2009

Список Related справа на этой странице содержит несколько ссылок, которые предоставляют интересную информацию по теме.

В дополнение к этому списку есть много других вопросов SO, обсуждающих эту тему, таких как

... и многие другие

2 голосов
/ 29 июня 2009

Когда я работаю в C ++, у меня работает следующее:

  1. все открытые методы (за исключением ctor и dtor) блокировки класса, обеспечивающей безопасность потока

  2. частные методы не могут вызывать открытые методы

Это не общий метод предотвращения тупиков.

1 голос
/ 29 июня 2009

Среди различных способов входа в критические секции - семафоры и мьютексы являются самыми популярными.

  • Семафор - это механизм ожидания, а мьютекс - это механизм блокировки, хорошо, что концепция сбивает с толку большинство, но вкратце, поток, активирующий мьютекс, может только деактивировать его. Имея это в виду ...

  • Не разрешать каким-либо процессам блокировать частичное отсутствие ресурсов, если процессу требуется 5 ресурсов, подождите, пока все не станут доступны.

  • если вы используете здесь семафор, вы можете разблокировать / отменить ожидание ресурса, занятого другим потоком. под этим я подразумеваю упреждение - еще одна причина.

Эти 2, по моему мнению, являются основными условиями, остальные 2 из 4 общих предосторожностей могут быть связаны с ними.

Если вы не согласны, пожалуйста, добавьте комментарии. Я уже поздно, позже я добавлю более ясное и ясное объяснение.

1 голос
/ 29 июня 2009

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

Другой вариант - вместо этого сделать асинхронные вызовы . Однако получить возвращаемые значения сложнее.

Примечание : Действительно, система передачи сообщений реализована с использованием критической секции, которая блокирует очередь вызовов, но она отвлекается.

1 голос
/ 29 июня 2009

Вы должны очень тщательно кодировать многопоточные программы. Там нет кратчайшего пути, вы должны понимать ход вашей программы, в противном случае вы будете обречены.

0 голосов
/ 19 июля 2018

Одним из способов является использование неблокирующей функции блокировки. Например, в ржавчине Вы можете использовать std::sync::Mutex::try_lock вместо std::sync::Mutex::lock.

Так что, если у вас есть этот пример кода:

fn transfer(tx: &Mutex<i32>, rx: &Mutex<i32>, amount: i32) -> () {
    let mut tx = tx.lock().unwrap();
    let mut rx = rx.lock().unwrap();

    *tx -= amount;
    *rx += amount;
}

Вместо этого вы можете сделать что-то вроде этого:

fn transfer(tx: &Mutex<i32>, rx: &Mutex<i32>, amount: i32) -> () {
    loop {
        // Attempt to lock both mutexes
        let mut tx = tx.try_lock();
        let mut rx = rx.try_lock();

        // If both locks were successfull,
        // i.e. if they currently are not
        // locked by an other thread
        if let Ok(ref mut tx) = tx {
            if let Ok(ref mut rx) = rx {
                // Perform the operations needed on
                // the values inside the mutexes
                **tx -= amount;
                **rx += amount;

                // Exit the loop
                break;
            }
        }
        // If at least one of the locks were
        // not successful, restart the loop
        // and try locking the values again.

        // You may also want to sleep the thread
        // here for a short period if You think that
        // the mutexes might be locked for a while.
    }
}
0 голосов
/ 18 апреля 2013

СЛЕДУЮЩИЙ АЛГОРИТМ ИСПОЛЬЗУЕТСЯ, ЧТОБЫ ИЗБЕЖАТЬ СМЕРТИ:

Алгоритм банкира

- Вводить менее жесткие условия, чем при предотвращении взаимоблокировок, в попытке улучшить использование ресурсов

- Безопасное состояние

• Операционная система может гарантировать, что все текущие процессы могут завершить свою работу в течение конечного времени

- небезопасное состояние

• Не означает, что система заблокирована, но ОС не может гарантировать, что все текущие процессы смогут завершить свою работу в течение конечного времени

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

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