使用多个线程时,共享内存需要被关键部分锁定。但是,使用关键部分会导致潜在的死锁。如何避免它们?
答案 0 :(得分:10)
一种方法是使用关键部分的层次结构。如果您确保永远不会在其中一个子项中输入父关键部分,则不会发生死锁。困难在于强制执行此层次结构。
答案 1 :(得分:5)
答案 2 :(得分:2)
当我使用C ++时,以下内容适用于我:
线程安全类锁的所有公共方法(不包括ctor和dtor)
私有方法无法调用公共方法
这不是一般的死锁避免方法。
答案 3 :(得分:1)
您必须非常仔细地编写多线程程序。没有捷径,你必须了解你的程序流程,否则你将注定失败。
答案 4 :(得分:1)
您可以通过消息传递(同步和异步调用)来避免关键部分。当使用同步调用时,您仍然必须确保不进行循环调用,其中线程A向线程B询问问题,并且B需要问A问题是否能够响应。 / p>
另一个选择是改为异步调用。但是,获取返回值更加困难。
注意:实际上,消息传递系统是使用锁定调用队列的关键部分实现的,但它被抽象出来。
答案 5 :(得分:1)
在进入关键部分的各种方法中 - 信号量和互斥量是最受欢迎的。
信号量是一种等待机制,而互斥锁是一种锁定机制,这个概念最让人困惑,但简而言之,激活互斥锁的线程只能停用它。考虑到这一点......
如果进程需要5个资源,请不要让任何进程锁定部分资源,等待所有资源都可用。
这两个根据我的基本条件,其余2个共同的4个注意事项可以与这些相关。
如果你不同意ps添加评论。我已经迟到了,我稍后会添加一个更清晰,更清晰的解释。
答案 6 :(得分:0)
使用以下算法来避免死锁:
银行家的算法
- 为了获得更好的资源利用率,在防止死锁方面实施不那么严格的条件
- 安全状态
•操作系统可以保证所有当前流程都能在有限的时间内完成工作
- 不安全状态
•并不意味着系统已陷入僵局,但操作系统无法保证所有当前流程都能在有限的时间内完成工作
- 仅在分配导致安全状态时才要求将资源分配给进程。 - 它有许多弱点(例如需要固定数量的进程和资源)阻止它在实际系统中实现
答案 7 :(得分:0)
一种方法是使用非阻塞锁定功能。例如,在锈病中,您可以使用public static AuthenticationBuilder AddAzureAD(
this AuthenticationBuilder builder,
string scheme,
string openIdConnectScheme,
string cookieScheme,
string displayName,
Action<AzureADOptions> configureOptions) {
AddAdditionalMvcApplicationParts(builder.Services);
builder.AddPolicyScheme(scheme, displayName, o => {
o.ForwardDefault = cookieScheme;
o.ForwardChallenge = openIdConnectScheme;
});
builder.Services.Configure(
TryAddOpenIDCookieSchemeMappings(scheme, openIdConnectScheme, cookieScheme));
builder.Services.TryAddSingleton<IConfigureOptions<AzureADOptions>, AzureADOptionsConfiguration>();
// They put in their custom OpenIdConnect configuration, but I can't see how to get at the events.
builder.Services.TryAddSingleton<IConfigureOptions<OpenIdConnectOptions>, OpenIdConnectOptionsConfiguration>();
builder.Services.TryAddSingleton<IConfigureOptions<CookieAuthenticationOptions>, CookieOptionsConfiguration>();
builder.Services.Configure(scheme, configureOptions);
builder.AddOpenIdConnect(openIdConnectScheme, null, o => { });
builder.AddCookie(cookieScheme, null, o => { });
return builder;
}
代替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;
}