类A和类B之间的线程同步:锁应该放在哪里
本文关键字:在哪里 同步 线程 和类 之间 | 更新日期: 2023-09-27 18:06:07
那么让我们假设我们有类A和类b。创建了类A的多个实例,每个实例在自己的线程上运行。让我们假设类B中有一堆资源,类a的所有实例都需要访问这些资源,但我希望一次只有一个线程操作这些资源。最明显的选择是lock语句。
我的问题是,锁应该在类B中(对于资源的getter和setter),或者如果它在类A中本身是相同的?(如下图所示)
class A
{
B b;
public A(B _b)
{
b = _b;
}
void DoStuff()
{
lock (this)
{
b.resource = "new values"
}
}
}
我希望你的问题很清楚。
首先,不要锁定this
。这只会导致死锁。
并且让A
的每个实例锁在它们自己或它们自己的对象上是行不通的。
- 使用一个单独的对象,
object lockObject = new object();
锁定。 - lockObject应该在作用域和生命周期内尽可能接近受保护的资源。 设置lockObject为私有对象。
在您的例子中,第2点)指出lockobject应该是B
的私有成员。
您仍然必须正确地编写B
的所有方法。
假设你说:
but I want only one thread manipulating those resources at one time
那么,是的,他们需要在B
类。目前的例子在A
类中是足够公平的,但由于B
是公共类,其他一些队友可能决定使用您的B
类及其资源,如果您不提供锁定它的接口,那么您想要的报价将无法满足
如果您想从ONLY A访问B的资源(假设有一个类A的实例!,如果不是,那么你有一个问题,因为每个a对象使用自己的锁对象-这是无用的),我认为这是一个选择的问题。这两种情况都适用。但是,当您需要从其他类访问B的资源时,这是有意义的。例如,你有一个类C,它访问B的资源。那么,A类中的锁在这里不起作用。问题在于锁语句中使用的对象。用不同的方式思考,把对象放在B中,而不是放在a或其他类中。在类A中不使用语句锁(this),而是使用同步。对象,可以在锁语句中使用。例如:
void DoStuff()
{
lock (b.LockObject)
{
b.resource = "new values"
}
}
正如您所说,您还可以在资源getter/setter中使用lock语句。通过这种方式,您不需要记住在需要时锁定B对象,特别是在不同的类中使用(当然除了A)。我认为最后的选择是一个设计选择。如果你还需要非线程安全版本的资源getter/setter,使用上面的例子更有意义。