Understanding of lock Statement in C# (C Sharp)

You might be working in a multithreaded application wherein more than one thread can access your code at the same time. There are certain critical situations wherein the code has to be accessed by only thread at a time.



In such cases, you can use lock statement to lock such block of code. The lock can be obtained by only one thread at a time. If another thread is trying to access the locked code, then it has to wait until the earlier thread finishes its job and then it can acquire the lock and execute the code.

Lock can be acquired using the following syntax:

lock(expression) {
//Code to be locked
}

In this syntax, expression can accept any reference type. There are certain restrictions in the expression based on which locking has to happen:

• Expression cannot be a value type
• Even though the expression can accept any reference type, ensure that you do not use the following as expression since it might lead to serious threading issues:
o this
o typeOf(<specific type>)
o “<string>”
Though these values are legal, they are not recommended.
• It is recommended that the reference type used as expression doesn’t have its access modifier as public

The syntax mentioned above is equivalent to:

Object object1 = <expression>;
Monitor.Enter(object1);
try {
//code to be locked
}
finally {
Monitor.Exit(object1);
}

Note that Monitor class belongs to System.Threading namespace.

For better understanding of why locking is required, consider the following code scenario:

class sampleClass {
private int member1;
sampleClass(int data1) {
member1 = data1;
}
public void criticalComputation(int data) {
if(member1 < 0) {
throw new Exception(“Member1 cannot be negative”);
}
if(member1 > data) {
member1 -= data;
}
else {
Console.WriteLine(‘Insufficient Value in member1”);
}
}
}

In this example, there will be no problem as long as your application is single threaded and only one thread is accessing the criticalComputation method at a time. Assume that the member1 value is initiated to 100. You call the criticalComputation method with the parameter 90. Control enters your code block. Since 100> 0 , it moves into computation. Now member1 value will be set to 100-90 which is 10. The next call to the method will execute with the member1 value as 10.

But this doesn’t happen in the same way in multithreaded application. Assume that your member1 is initialized to 100. Now two threads are accessing your code at the same time. First thread calls the criticalComputation method with the value 90 and second thread with the value 50.

Both the threads are accessing your code at the same time and both have checked the condition member1>0. Since member1=100, both the threads satisfy the conditions member1>0 and member1>data and they continue with the computation. When thread1 is performing the computation, member1 will be 100-90 = 10. Thread2 does the computation and member1 will be 10-50 = -40.

Is this the expected result? NO. This will throw the user defined exception coded above. How can you avoid this situation? You can easily avoid it using lock statement. The above code is modified to use lock statement as shown below:

class sampleClass {
private int member1;
private Object lockObj = new Object();
sampleClass(int data1) {
member1 = data1;
}
public void criticalComputation(int data) {
if(member1 < 0) {
throw new Exception(“Member1 cannot be negative”);
}
lock(lockObj) {
if(member1 >= data) {
member1 -= data;
}
else {
Console.WriteLine(‘Insufficient Value in member1”);
}
}
}

}
class testClass {
sampleClass obj = new sampleClass(100);
Thread[] threadInstances = new Thread[20];
for (int index = 0; index < 20; index++) {
Thread sample = new Thread(obj.criticalComputation);
threadInstances[index] = sample;
}
for (int index = 0; index < 20; index++)
{
threadInstances[index].Start();
}
}

In this modified code, you have locked the computation code in criticalComputation method. In Main method of testClass, you initialize and start 20 threads in one go. So there are enough chances for multiple threads to access code of criticalComputation method in parallel way. But still, to your surprise the exception stating “Member1 cannot be negative” will never be thrown since the synchronization of threads is achieved using lock statement.

| .NET 3.5 Framework – New Features and Benefits | Overview of .NET Framework 3.5 Architecture | Overview of Unary Operators of C# (C Sharp) | Understanding of Checked and Unchecked Statement Type of C# (C Sharp) | Understanding of fixed Statement in C# (C Sharp) | Understanding of lock Statement in C# (C Sharp) | Understanding of Logical Operators (Bitwise, Boolean) in C# (C Sharp) | Understanding of Logical Operators (Conditional) in C# (C Sharp) |


“Amazon and the Amazon logo are trademarks of Amazon.com, Inc. or its affiliates.”

| Privacy Policy for www.dotnet-guide.com | Disclosure | Contact |

Copyright - © 2004 - 2024 - All Rights Reserved.