简体   繁体   English

为什么这个锁定声明不起作用?

[英]why doesn't this lock statement work?

class Program
{
    static object test = new object();
    static void Main(string[] args)
    {
        new Program().test2();
        Console.ReadKey();
    }

    public void test1()
    {
        lock (test)
        {
            Console.WriteLine("test1");
        }
    }

    public void test2()
    {
        lock (test)
        {
            test1();
            Console.WriteLine("test2");
        }
    }
}

Is the code above supposed to first finish statements in lock statement of test2() then go to the test1()? 上面的代码是否应首先在test2()的lock语句中完成语句然后转到test1()? (ie Doesn't the output supposed to be like this? : test2 test1 ) (即输出不应该是这样的吗?:test2 test1)

No. The sequence of events (identation represents call stack or logical operations) is: 否。事件序列(标识表示调用堆栈或逻辑操作)是:

  • Main calls test2 主要叫test2
    • test2 attempts to acquire the monitor associated with the test object (start of the lock statement) test2尝试获取与测试对象关联的监视器( lock语句的开始)
      • Monitor is currently unowned. Monitor目前尚未拥有。 Success! 成功!
      • The current thread now "owns" that monitor, with a count of 1 当前线程现在“拥有”该监视器,计数为1
    • test2 calls test1 test2调用test1
      • test1 attempts to acquire the monitor for the test object (start of the lock statement) test1尝试获取测试对象的监视器( lock语句的开始)
        • Monitor is currently owned... but by the current thread. Monitor目前拥有...但是当前的线程。 Success! 成功!
        • The current thread still "owns" the monitor, with a count of 2 当前线程仍然“拥有”监视器,计数为2
      • test1 prints "test1" test1打印“test1”
      • test1 releases the monitor (end of the lock statement) test1释放监视器( lock语句的结尾)
        • The current thread still "owns" the monitor, with a count of 1 当前线程仍然“拥有”监视器,计数为1
      • test1 returns test1返回
    • test2 prints "test2" test2打印“test2”
    • test2 releases the monitor (end of the lock statement) test2释放监视器( lock语句的结尾)
      • The monitor is now unowned (so another thread could acquire it) 监视器现在是无主的(因此另一个线程可以获取它)
    • test2 returns test2返回

It's important to note that monitors are re-entrant - if the current thread already owns the monitor, then another attempt to acquire it will just increase the count, rather than blocking. 重要的是要注意监视器是可重入的 - 如果当前线程已经拥有监视器,那么另一次获取它的尝试只会增加计数,而不是阻塞。

If monitors weren't re-entrant, the output wouldn't be "test2, test1" - it would just be deadlock. 如果监视器不是可重入的,那么输出将不是“test2,test1” - 它只会是死锁。

A monitor is re-entrant on the same thread. 监视器可以重新进入同一个线程。 Pretty important to avoid accidental dead-lock, your code would freeze solidly if it didn't have that behavior. 为避免意外死锁非常重要,如果没有这种行为,您的代码会严格冻结。

A Mutex is also re-entrant, a Semaphore is not. 互斥体也是可重入的,信号量不是。

The implementation is pretty straight forward. 实施非常简单。 A Monitor stores two pieces of information. 监视器存储两条信息。 The owner Thread.ManagedId of the thread that entered it and a counter that counts the number of times it was entered. 输入它的线程的所有者Thread.ManagedId和计算输入次数的计数器。 So the first lock can enter since it isn't owned, it sets the owner to your thread and the count to 1. The second lock is allowed to enter since the thread ID matches, the count increments to 2. At the end of the second lock, the count decrements to 1 again. 因此,第一个锁可以进入,因为它不是拥有的,它将所有者设置为您的线程并将计数设置为1.允许第二个锁进入,因为线程ID匹配,计数增加到2.结束时第二次锁定,计数再次减少到1。 At the end of the first, the count decrements to 0 and that resets the owner. 在第一个结束时,计数减少到0并重置所有者。

Locking isn't supposed to be used in single-threaded scenarios. 锁定不应该在单线程场景中使用。 It's purpose is to be used in cross threads calls to the same methods or object instances. 它的目的是用于对相同方法或对象实例的跨线程调用。

The behavior you're noticing is normal. 你注意到的行为是正常的。

You will typically want to synchronize access to resources (variables, collections, etc) when two or more threads can access them at the same time. 当两个或多个线程可以同时访问资源时,您通常希望同步对资源(变量,集合等)的访问。

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM