Zeu*_*eus 2 c# multithreading locking task
我们有一个代码,其中两个锁以不同的方法锁定在同一对象上。这两种方法都可以从不同的线程调用。
这会进入僵局吗?我们应该在两种方法中使用相同的 lock1 吗?
使用两个不同的锁的原因是移除发生在并行运行的各种任务中,但更新列表发生在每隔几秒运行一次的新线程中。
private static Object Lock1 = new Object();
private static Object Lock2 = new Object();
private static List<string> list = new List<string>();
public void Method1()
{
lock(Lock1)
{
//update list
}
}
public void Method2()
{
lock(Lock2)
{
//remove from list
}
}
Run Code Online (Sandbox Code Playgroud)
感谢您的健康讨论,我已更新我的代码以使用 .net 提供的线程安全集合 BlockingCollection。我继续使用 lock1,因为我需要控制列表可以包含的对象数量。我现在已经删除了 lock2,因为线程安全列表不需要它。
这会进入僵局吗?
不。
我们应该在两种方法中使用相同的 lock1 吗?
是的。在多个线程上访问特定对象时,您应该始终锁定同一个锁定对象。在您的特定情况下,您显示的代码完全错误且已损坏。每个列表应该有一个锁,并且每次访问列表时始终取出该锁。
如果您正在更新列表变量,那么同样的事情 - 您应该为列表变量设置一个锁,并且每次出于任何原因访问该变量时都需要在该锁下。
使用两个不同的锁的原因是移除发生在并行运行的各种任务中,但更新列表发生在每隔几秒运行一次的新线程中。
那没关系。所有更新,无论是删除还是其他,都必须在同一个锁下发生。
如果您处于频繁阅读者多而作者少的情况下,则有针对这些情况的专用锁。但这不是你的场景。
你没有问的一些问题:
什么导致死锁?
void Transfer(Account a1, Account a2, decimal amount)
{
lock(a1)
{
lock(a2)
{
// do the transfer
}
}
}
Run Code Online (Sandbox Code Playgroud)
假设线程 X 调用Transfer(savings, checking, 100)并获得了锁定savings。然后我们切换到调用Transfer(checking, savings, 50). 我们锁定checking,然后尝试锁定savings,但不能,因为 X 拥有它。然后我们切换回 X,它试图锁定checking,但不能,因为 Y 拥有它。然后我们永远等待。那是一个僵局。
锁定“嵌套”在同一线程上的同一对象是否会导致死锁?
不。答案是错误的。锁定您已经在线程上拥有的锁会自动成功。
我应该使用更好的技术吗?
是的。多线程程序很难正确编写。如果必须,请使用高级对象,例如多线程集合或不可变集合,这些对象旨在无需显式锁定即可有效解决这些问题。
你也应该阅读