A类和B类之间的线程同步:锁定在哪里?

时间:2014-05-31 09:47:46

标签: c# multithreading concurrency locking

所以我们假设我们有A类和B类。创建了多个A类实例,每个实例都在自己的线程上运行。让我们假设B类中有一堆资源都是A类的实例需要访问,但我只希望一次操作这些资源的一个线程。显而易见的选择是锁定声明。

我的问题是,锁是否应该在B类(对于资源的获取者和设置者),或者它是否在A类本身中是相同的? (如下图所示)

class A
{

    B b;

    public A(B _b)
    {
        b = _b;
    }

    void DoStuff()
    {
        lock (this)
        {
            b.resource = "new values"
        }
    }


}

我希望问题很清楚。请询问您是否需要更多详细信息。

3 个答案:

答案 0 :(得分:2)

首先,不要锁定this。这只会引发僵局 让A每个锁定自己或他们自己的对象的实例都不起作用。

  1. 使用单独的对象object lockObject = new object();锁定。
  2. 在范围和生命周期中,lockObject应尽可能接近受保护资源。
  3. 将lockObject设为私有。
  4. 在您的情况下,第2点)表示锁定对象应该是B的私有成员。

    然后,您仍然需要正确编写所有B方法。

答案 1 :(得分:0)

假设你说:

but I want only one thread manipulating those resources at one time

然后,是的,他们需要在班级B。对于当前示例在A课程中是公平的,但由于B是公共课,其他一些队友可以决定使用您的B课程及其资源,如果您不喜欢不提供用于锁定的界面,那么您对报价的要求将不会得到满足

答案 2 :(得分:0)

如果你想从ONLY A访问B的资源(假设有一个类A的sinle实例!,如果没有那么你有问题,因为每个A对象使用uits自己的锁对象 - 这个 - 这是无用的),我认为这是一个选择问题。两者都适用于这种情况。但是,无论何时需要从其他类访问B的资源,这都是有意义的。例如,你有C级访问B的资源。然后,你在A类中的锁在这里不起作用。问题是您在lock语句中使用的对象。以不同的方式思考并将对象放在B中,而不是放在A或其他类中。而不是A类中的语句锁(this),而是进行同步。 B中的对象,可以在锁定语句中使用。例如:

void DoStuff()
{
    lock (b.LockObject)
    {
        b.resource = "new values"
    }
}

正如您所说,您还可以在资源getter / setter中使用lock语句。通过这种方式,您无需在需要时记住锁定B对象,尤其是在不同的类中使用(当然不是A)。我想,最终的选择是设计选择。如果您还需要非线程安全版本的资源getter / setter,使用上面的示例更有意义。