3

I'm trying to wrap my mind around what exactly happens in the lock statement.

If I understood correctly, the lock statement is syntactic sugar and the following...

Object _lock = new Object();

lock (_lock)
{
    // Critical code section
}

...gets translated into something roughly like:

Object _lock = new Object();

Monitor.Enter(_lock);
try
{
    // Critical code section
}
finally { Monitor.Exit (_lock); }

I have used the lock statement a few times, and always created a private field _lock, as a dedicated synchronization object. I do understand why you should not lock on public variables or types.

But why does the compiler not create that instance field as well? I feel there might in fact be situations where the developer wants to specify what to lock on, but from my experience, in most cases that is of absolutely no interest, you just want that lock! So why is there no parameterless overload of lock?

lock()
{
   // First critical code section
}

lock()
{
   // Second critical code section
}

would be translated into (or similar):

[DebuggerHidden]
private readonly object _lock1 = new object()

[DebuggerHidden]
private readonly object _lock2 = new object()

Monitor.Enter(_lock1);
try
{
    // First critical code section
}
finally { Monitor.Exit(_lock1); }

Monitor.Enter(_lock2);
try
{
    // Second critical code section
}
finally { Monitor.Exit(_lock2); }

EDIT: I have obviously been unclear concerning multiple lock statements. Updated the question to contain two lock statements.

4

4 に答える 4

3

The state of the lock needs to be stored. Whether or not it was entered. So that another thread that tries to enter the same lock can be blocked.

That requires a variable. Just a very simple one, an plain object is enough.

A hard requirement for such a variable is that it is created before any lock statement uses it. Trying to create it on-the-fly as you propose creates a new problem, there's a now a need to use a lock to safely create the variable so that only the first thread that enters the lock creates it and other threads trying to enter the lock are blocked until it is created. Which requires a variable. Etcetera, an unsolvable chicken-and-egg problem.

于 2012-12-29T21:07:46.253 に答える
2

There can be situations when you will need two different lock's, which are independent of each other. Meaning when one 'lockable' part of code is locked other 'lockable' should not be locked. That's why there is ability to provide lock objects - you can have several of them for several independent lock's

于 2012-12-29T21:15:19.243 に答える
1

変数のないものが機能するためには、次のいずれかを行う必要があります。

  • ロックブロックごとに1つの自動生成されたロック変数を用意します(これは、2つの異なるロックブロックを同じ変数にロックすることはできないことを意味します)
  • 同じクラスのすべてのロックブロックに同じロック変数を使用します(つまり、2つの独立したものを保護することはできません)

さらに、それらをインスタンスレベルにするか静的にするかを決定するという問題もあります。

結局、言語設計者は、ある特定のケースでの単純化が、コードを読んでいる間に導入された曖昧さの価値があるとは感じていなかったと思います。スレッデッドコード(これがロックを使用する理由です)は、すでに正しく記述して検証するのが困難です。それを難し​​くすることは良くないことです。

于 2013-01-01T02:27:27.427 に答える
0

Allowing for an implicit lock object might encourage the use of a single lock object, which is considered bad practice. By enforcing the use of an explicit lock object, the language encourages you to name the lock something useful, such as "countIncementLock".

A variable named thusly would not encourage developers to use the same lock object when performing a completely separate operation, such as writing to a stream of some kind.

Therefore, the object could be writing to a stream on one thread, while incrementing a counter on another thread, and neither of the threads would necessarily interfere with each other.

The only reason why the language wouldn't do this is because is because it would look like a good practice, but in reality would be hiding a bad practice.

Edit:

Perhaps the designers of C# did not want implicit lock variables because they thought it might encourage bad behavour.

Perhaps the designers did not think of implicit lock variables at all, because they had other more important things to think about first.

If every C# developer knew exactly what was happening when they wrote lock(), and they knew the implications, then there's no reason why it shouldn't exist, and no reason why it shouldn't work how you're suggesting.

于 2012-12-29T21:17:01.217 に答える