In C#, the lock
statement is used to achieve thread synchronization, which helps prevent multiple threads from accessing a shared resource simultaneously. This is crucial to avoid data corruption and race conditions in multi-threaded applications.
The lock
statement takes an object as its argument, which serves as the synchronization token. When a thread encounters a lock
statement, it attempts to acquire the lock on the specified object. If the lock is available (i.e., no other thread is currently holding the lock), the thread acquires the lock and proceeds to execute the code block inside the lock
statement.
While one thread holds the lock, any other thread that tries to enter the same lock
statement for the same object will be blocked and forced to wait until the lock is released by the owning thread. This way, only one thread can execute the critical section of code protected by the lock
statement at any given time.Here's the basic syntax of the lock
statement in C#:
lock (lockObject)
{
// Critical section: code that should be executed atomically
}
Where lockObject
is an object used as the synchronization token.
It's essential to choose a suitable object as the synchronization token. Typically, developers use dedicated objects (e.g., private readonly object syncObject = new object();
) to avoid potential deadlocks and unintended interactions with other parts of the code.Here's an example of how the lock
statement is used to protect a shared resource:
class SharedResource
{
private readonly object syncObject = new object();
private int count = 0;
public void Increment()
{
lock (syncObject)
{
// Accessing the shared resource safely within the critical section
count++;
}
}
public int GetCount()
{
lock (syncObject)
{
return count;
}
}
}
In this example, the Increment
and GetCount
methods are protected using the lock
statement to ensure that multiple threads can safely access and modify the count
variable. By doing so, you avoid potential race conditions and ensure the integrity of the shared resource.