why doesn't this lock statement work?

余生颓废 提交于 2020-01-13 11:10:49

问题


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()? (i.e. Doesn't the output supposed to be like this? : test2 test1 )


回答1:


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. 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. At the end of the first, the count decrements to 0 and that resets the owner.




回答2:


No. The sequence of events (identation represents call stack or logical operations) is:

  • Main calls test2
    • test2 attempts to acquire the monitor associated with the test object (start of the lock statement)
      • Monitor is currently unowned. Success!
      • The current thread now "owns" that monitor, with a count of 1
    • test2 calls test1
      • test1 attempts to acquire the monitor for the test object (start of the lock statement)
        • Monitor is currently owned... but by the current thread. Success!
        • The current thread still "owns" the monitor, with a count of 2
      • test1 prints "test1"
      • test1 releases the monitor (end of the lock statement)
        • The current thread still "owns" the monitor, with a count of 1
      • test1 returns
    • test2 prints "test2"
    • test2 releases the monitor (end of the lock statement)
      • The monitor is now unowned (so another thread could acquire it)
    • test2 returns

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.




回答3:


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.



来源:https://stackoverflow.com/questions/11272616/why-doesnt-this-lock-statement-work

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!