Why do we pass an object to the statement lock?

4

I'm working with multithreading and fell into a competition case. More than one thread accessed an I / O operation on the same file and so an exception was thrown. To solve the problem, I did so:

private static object padlock = new object();

private static void SaveFile(string content) {
    lock (padlock) {
        Directory.CreateDirectory(Dir);
        File.AppendAllText(FilePath, content);
    }
}

The object padlock is passed to lock . I learned it as if it were a cake recipe (which is awful!). I do not know why I need the object padlock .

    
asked by anonymous 10.11.2017 / 12:21

2 answers

3

This has to do with atomicity . This ensures that the object can not be accessed by other parts of the code concurrently until it is released, thus ensuring that the intermediate state it is throughout the block is not accessible.

This is controlled by the framework . In fact this code is just syntactic sugar for:

bool lockWasTaken = false;
var temp = padlock;
try {
    Monitor.Enter(temp, ref lockWasTaken);
    Directory.CreateDirectory(Dir);
    File.AppendAllText(FilePath, content);
} finally {
    if (lockWasTaken) Monitor.Exit(temp);
}

So it's the class Monitor that controls this access.

Often using lock loses the competition advantage by getting only the burden.

Note that the locking operation is only occurring in the application and not in the external resource (file). If allowed the external resource can still be accessed by other applications and give problem. So locking is just preventing another thread from running the same code at the same time.

    
10.11.2017 / 12:29
1

This object is going to " save " lock information.

When the first thread enters the method and calls the lock , the obj object (or padlock , in your example) is going to be with the status locked and prevent another thread from entering.

It is just the object that holds this information.

From C # 4.0, the lock statement is compiled this way:

bool lockWasTaken = false;
var temp = obj;
try
{
    Monitor.Enter(temp, ref lockWasTaken);
    // Operação thread unsafe...
}
finally
{
    if (lockWasTaken)
    {
        Monitor.Exit(temp); 
    }
}

Where the original method is this:

private static readonly Object obj = new Object();

// Dentro de um método XYZ
lock (obj)
{
    // Operação thread unsafe...
}

Reference

    
10.11.2017 / 12:29