Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do we need to lock and object in C#?

This is something I've never understood. It almost seems like a hack to create a dummy object that gets locked, like the 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 couldn't the language designers make it so that

class Account  
{  
    decimal balance;   

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

would be equivalent?

like image 222
Deadly Nicotine Avatar asked Nov 05 '16 22:11

Deadly Nicotine


People also ask

Why do we use lock statement in C?

The lock statement acquires the mutual-exclusion lock for a given object, executes a statement block, and then releases the lock. While a lock is held, the thread that holds the lock can again acquire and release the lock. Any other thread is blocked from acquiring the lock and waits until the lock is released.

What is the purpose of the lock keyword?

The lock keyword makes it possible to block a section of code while working with another thread. To enter a section of code where an existing thread already exists, the other thread must wait until the previous thread's execution completes. As soon as the current thread in the function completes, the lock is released.

What do you mean by locking of objects?

An object-level lock is a mechanism when we want to synchronize a non-static method or non-static code block such that only one thread will be able to execute the code block on a given instance of the class. If a thread wants to execute a synchronized method on the given object.

Is lock an object?

Lock Object is a feature offered by ABAP Dictionary that is used to synchronize access to the same data by more than one program. Data records are accessed with the help of specific programs. Lock objects are used in SAP to avoid the inconsistency when data is inserted into or changed in the database.


2 Answers

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

You may have any number of unrelated critical sections in your code, and each one will be locking a different object. A parameterless lock statement the likes of the one you suggest wouldn't be able to distinguish between many critical sections.

EDIT

Although it might seem obvious, it's worth noting that every single part needing to enter a given critical section must have access to the locked object. So it's not a matter of creating an arbitrary instance just before and in the same scope than the lock statement.

like image 131
rucamzu Avatar answered Sep 23 '22 14:09

rucamzu


I think the confusion lies in what the lock keyword is doing. It is not saying only 1 thread can enter that section of code but it is saying 2 things:

  1. only one thread can enter this section of code who has thisLock
  2. Any other section which is locked with thisLock is also not to be allowed entry by any thread except this thread since this thread has thisLock.

What you are suggesting would only be doing the 1st one but not both. 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 thread, say T1, is doing the withdrawal part with the first lock, all other sections of the class with lock(thisLock) are not allowed entry by any other thread as well. However, the part with thisLock2 is allowed to be entered by other threads.

The best way to think of the lock keyword, at least it helped me when I was learning was to think of it as a hostage. In other words, when certain parts of the code are being executed it needs to take a hostage (thisLock) in your example. So once that thisLock is taken as hostage, no other thread can take it as hostage until that thread releases the hostage. Therefore, all other sections of code which also need the same hostage, become unavailable.

like image 39
CodingYoshi Avatar answered Sep 21 '22 14:09

CodingYoshi