Why do we need to block objects in C #?

This is something that I never understood. It seems like a hack to create a dummy object that gets lock ed, like an example

 class Account { decimal balance; private Object thisLock = new Object(); public void Withdraw(decimal amount) { lock (thisLock) { if (amount > balance) { throw new Exception("Insufficient funds"); } balance -= amount; } } } 

from https://msdn.microsoft.com/en-us/library/c5kehkcz.aspx .

Why language developers couldn’t do this so that

 class Account { decimal balance; public void Withdraw(decimal amount) { lock { if (amount > balance) { throw new Exception("Insufficient funds"); } balance -= amount; } } } 

will be equivalent?

+5
source share
2 answers

The instance passed to lock serves to identify the critical section .

Your code can have any number of unrelated critical sections, and each of them will block another object. A parameterless lock statement, similar to the one you are proposing, will not be able to distinguish many critical sections.

EDIT

Although this may seem obvious, it is worth noting that each individual part that must be included in this critical section must have access to a locked object. Thus, it is not a matter of creating an arbitrary instance immediately before and in the same scope as the lock statement.

+7
source

I think the confusion is what the keyword lock does. This does not say that only 1 thread can enter this section of code, but it says 2 things:

  • only one thread can enter this section of code that has thisLock
  • Any other section that is locked by thisLock should also not be allowed to enter any stream other than this stream, since this stream has thisLock.

What you offer will do only one thing, but not both. Take a look at this example:

 class Account { decimal balance; private Object thisLock = new Object(); private Object thisLock2 = new Object(); public void Withdraw(decimal amount) { lock (thisLock) { if (amount > balance) { throw new Exception("Insufficient funds"); } balance -= amount; } // more code here but no locking necessary... lock(thisLock) { // only one thread can enter here who has thisLock } lock (thisLock2) { // If T1 (thread1) is working with thisLock, T2 can come here since it has nothing to do // with thisLock. } } public void AnotherOperation() { lock (thisLock) { // code here... } } public void YetAnotherOperation() { lock (thisLock) { // code here... } } } 

When a stream, say T1, does part of the output with the first lock, all other sections of the class with a lock (thisLock) are not allowed to write to any other thread. However, the part with this Lock2 is allowed for input by other threads.

The best way to think of a blocking keyword, at least it helped me when I was studying, was to think of it as a hostage. In other words, when certain parts of the code are executed, your example requires a capture (thisLock). Therefore, when this box is considered a hostage, no other thread can consider it a hostage until this thread releases the hostage. Therefore, all other sections of the code, which also need the same hostage, become inaccessible.

0
source

Source: https://habr.com/ru/post/1259346/


All Articles