问题
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
- test1 attempts to acquire the monitor for the test object (start of the
- 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
- test2 attempts to acquire the monitor associated with the test object (start of the
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