简体   繁体   English

如果实例可公开访问,则使用lock(this)

[英]use of lock(this) if the instance is publicly accessible

I was looking at the answer for not using "this" in the lock, if the instance is publicly accessible. 如果实例是公开可访问的,我正在寻找在锁中不使用“this”的答案。 I tried below example , I was thinking Method1 will be not called since lock is already acquired in Main method on the instance. 我尝试下面的例子,我认为不会调用Method1,因为已经在实例的Main方法中获取了锁。 But Method1 is called Method2 wait indefinitely. 但Method1被称为Method2无限期等待。 Explanation for the same will be appreciated . 对此的说明将不胜感激。

class Program
{
    static void Main(string[] args)
    {
        Tracker tracker = new Tracker();
        lock (tracker)
        {
            Parallel.Invoke(() => tracker.Method1(),
                () => tracker.Method2());
        }
    }
}

class Tracker
{
    private int number = 6;
    public void Method1()
    {
        lock (this)
        {
            number *= 5;
            Console.WriteLine("Method1: " + number);
            number /= 4;
            Console.WriteLine("Method1: " + number);
        }
    }

    public void Method2()
    {
        lock (this)
        {
            number *= 3;
            Console.WriteLine("Method2: " + number);
            number /= 2;
            Console.WriteLine("Method2: " + number);
        }
    }
}

It's not impossible to lock on an object that's publicly accessible, it's just a really bad idea as it makes understanding the synchronization of an object much harder. 锁定一个可公开访问的对象并非不可能 ,这只是一个非常糟糕的主意,因为它难以理解对象的同步。 The general practice is to never lock on an object that is ever accessible outside of the scope of the current type because it makes it very easy to keep track of all of the possible places where the lock can be acquired, which makes it much easier to diagnose potential problems with the synchronization and to understand what, exactly is being synchronized, when looking through the code. 通常的做法是永远不要锁定在当前类型范围之外可以访问的对象,因为它可以很容易地跟踪可以获取锁的所有可能位置,这使得它更容易诊断同步的潜在问题,并在查看代码时了解正在同步的内容。

When you're synchronizing on an object that is publicly exposed it will work , it just means that if you run into a problem you have an enormous space to look through to try to figure out what the problematic interactions are. 当您在公开暴露的对象上进行同步时,它将起作用 ,这只意味着如果您遇到问题,您将有一个巨大的空间来查看,以试图找出有问题的交互是什么。 It also makes it much easier to end up with a deadlock when lots of different code in very different places is all interacting with an object being locked on. 当非常不同的地方的许多不同代码都与被锁定的对象进行交互时,它还使得更容易结束死锁。

From the documentation of Parallel.Invoke : Parallel.Invoke的文档:

Executes each of the provided actions, possibly in parallel. 执行每个提供的操作, 可能并行执行。

So here is what's happening: 所以这是正在发生的事情:

  • Your first action runs in the same thread as the main function call , 您的第一个操作在与主函数调用相同的线程中运行,
  • Locks in C# are re-entant , so Method1 can re-acquire the lock. C#中的锁是重要的 ,因此Method1可以重新获取锁。

The following code prints the thread id-s to prove that Main and Method1 runs in the same thread. 以下代码打印线程id-s以证明MainMethod1在同一个线程中运行。

class Program
{
    static void Main(string[] args)
    {
        Tracker tracker = new Tracker();
        Console.WriteLine("Main TID: " + Thread.CurrentThread.ManagedThreadId);
        lock (tracker)
        {
            Console.WriteLine("Main Acquired");
            Parallel.Invoke(() => tracker.Method1(),
                () => tracker.Method2());
        }
    }
}

class Tracker
{
    private int number = 6;
    public void Method1()
    {
        Console.WriteLine("Method1 TID: " + Thread.CurrentThread.ManagedThreadId);
        lock (this)
        {
            Console.WriteLine("Method1 Acquired");
        }
    }

    public void Method2()
    {
        Console.WriteLine("Method2 TID: " + Thread.CurrentThread.ManagedThreadId);
        lock (this)
        {
            Console.WriteLine("Method2 Acquired");
        }
    }
}

Outputs 输出

Main TID: 1
Main Acquired
Method1 TID: 1
Method1 Acquired
Method2 TID: 3

And then it hangs. 然后它挂了。 Thread ID -s show that Method1 runs in the same thread as Main . Thread ID -s显示Method1在与Main相同的线程中运行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如果不能公开访问,是否可以将自托管控制台应用程序用作 Signal R 服务器? - Is it possible to use a Self Hosted Console Application as a Signal R Server if it is not publicly accessible? 为类中的方法制作可公开访问的标志 - Making a publicly accessible flag for a method in a class 如何制作可公开访问的课程列表? - How to make a list of classes publicly accessible? 是否有一个公共可访问事件来标记ModalDialog关闭? - Is there a publicly accessible event to mark a ModalDialog close? 如何检查可公开访问的网址? - How can I check a url is publicly accessible? 注入的依赖项是公共可访问还是私有? - Should injected dependencies be publicly accessible or private? 如何将kml文件写入可公开访问的服务器? - How to write a kml file to publicly accessible server? 名称空间中的ASP.net C#公共可访问函数 - ASP.net c# publicly accessible functions in namespace 如何最好地在C#中实现可公开访问的常量 - How best to implement publicly accessible constants in C# 经过身份验证的用户如何访问可公开访问的驱动器? - How can an authenticated user access the drive that is publicly accessible?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM