multithreading 如何避免死锁?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1057054/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 01:02:49  来源:igfitidea点击:

How to avoid deadlocks?

multithreadinglanguage-agnosticconcurrency

提问by Dimitri C.

When using multiple threads, shared memory needs to be locked by critical sections. However, using critical sections causes potential deadlocks. How can they be avoided?

使用多线程时,共享内存需要被临界区锁定。但是,使用临界区会导致潜在的死锁。如何避免它们?

回答by Dimitri C.

One way is to use a hierarchy of critical sections. If you ensure that a parent critical section is never entered within one of its children, deadlocks cannot happen. The difficulty is to enforce this hierarchy.

一种方法是使用临界区层次结构。如果您确保父临界区从未进入其子临界区之一,则不会发生死锁。困难在于强制执行这种等级制度。

回答by Fredrik M?rk

The Relatedlist to the right on this page contains a few links that provides interesting information on the topic.

此页面右侧的相关列表包含一些提供有关该主题的有趣信息的链接。

In addition to that list, there are many other SO questions discussing the topic, such as

除了该列表之外,还有许多其他 SO 问题在讨论该主题,例如

...and many more

......还有更多

回答by Rhythmic Fistman

When I work in C++, the following works for me:

当我在 C++ 中工作时,以下对我有用:

  1. all public methods (excluding ctor and dtor) of a threadsafe class lock

  2. private methods cannot call public methods

  1. 线程安全类锁的所有公共方法(不包括 ctor 和 dtor)

  2. 私有方法不能调用公共方法

It's not a general deadlock avoidance method.

这不是一般的死锁避免方法。

回答by FelipeC

You must code multi-thread programs very carefully. There's no short-cut, you mustunderstand the flow of your program, otherwise you'll be doomed.

您必须非常小心地编写多线程程序。没有捷径可走,你必须了解你的程序的流程,否则你就注定失败。

回答by Dimitri C.

You can avoid critical sections by using message passinginstead (synchronous and asynchronous calls). When using synchronous calls, you still have to make sure not to make a circular call, in which thread A asks thread B a question, and B needs to ask A a question to be able to respond.

您可以通过使用消息传递(同步和异步调用)来避免临界区。使用同步调用时,还是要注意不要循环调用,线程A向线程B提问,B需要向A提问才能回答。

Another option is to make asynchronous callsinstead. However, it is more difficult to get return values.

另一种选择是进行异步调用。但是,获取返回值比较困难。

Note: Indeed, a message passing system is implemented using a critical section that locks the call queue, but it is abstracted away.

注意:确实,消息传递系统是使用锁定调用队列的临界区实现的,但它被抽象掉了。

回答by vks

Among the various methods to enter critical sections -- semaphores and mutexs are the most popular.

在进入临界区的各种方法中——信号量和互斥量是最流行的。

  • A semaphore is a waiting mechanism and mutex is a locking mechanism, well the concept is confusing to the most, but in short, a thread activating a mutex can only deactivate it. with this in mind...

  • Dont allow any process to lock partial no of resources, if a process need 5 resources, wait until all the are available.

  • if u use semaphore here, u can unblock/un-wait the resource occupied by other thread. by this i mean pre-emption is another reason.
  • 信号量是一种等待机制,互斥量是一种锁定机制,这个概念最容易混淆,但简而言之,激活互斥量的线程只能停用它。考虑到这一点......

  • 不允许任何进程锁定部分资源,如果一个进程需要 5 个资源,请等待所有资源都可用。

  • 如果你在这里使用信号量,你可以解除阻塞/解除等待其他线程占用的资源。我的意思是先发制人是另一个原因。

These 2 according to me are the basic conditions, the remaining 2 of the common 4 precautions can be related to these.

这2个按我说是基本情况,常见的4个注意事项中剩下的2个可以和这些有关。

If u dont agree ps add comments. I've gtg already late, I will later add a cleaner and clearer explanation.

如果你不同意 ps 添加评论。我已经迟到了 gtg,我稍后会添加一个更清晰、更清晰的解释。

回答by user2293912

THE FOLLOWING ALGORITHM IS USED TO AVOID DEADLOCK:

以下算法用于避免死锁:

Banker's Algorithm

银行家算法

–Impose less stringent conditions than in deadlock prevention in an attempt to get better resource utilization

– 施加比死锁预防更宽松的条件,以试图获得更好的资源利用

–Safe state

– 安全状态

?Operating system can guarantee that all current processes can complete their work within a finite time

?操作系统可以保证当前所有的进程都可以在有限的时间内完成他们的工作

–Unsafe state

– 不安全状态

?Does not imply that the system is deadlocked, but that the OS cannot guarantee that all current processes can complete their work within a finite time

? 不代表系统死锁,而是OS不能保证当前所有进程都能在有限时间内完成工作

–Requires that resources be allocated to processes only when the allocations result in safe states. –It has a number of weaknesses (such as requiring a fixed number of processes and resources) that prevent it from being implemented in real systems

– 要求仅当分配导致安全状态时才将资源分配给进程。– 它有许多弱点(例如需要固定数量的进程和资源),使其无法在实际系统中实施

回答by Mathias Magnusson

One way is by using a non-blocking locking function. As an example, in rust You could use std::sync::Mutex::try_lockinstead of std::sync::Mutex::lock.

一种方法是使用非阻塞锁定功能。例如,在 rust 中,您可以使用std::sync::Mutex::try_lock代替std::sync::Mutex::lock.

So so if you have this example code:

所以如果你有这个示例代码:

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;
}

You could instead do something like this:

你可以做这样的事情:

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.
    }
}