C# Lock keyword

Definition: lock ensures that when one thread is in the critical area of code, another thread does not enter the critical area. If another thread attempts to enter locked code, it will wait (that is, be blocked) until the object is released.

Monitor methods are static and can be called directly without generating an instance of the monitor class. In the. NET Framework, each object has a lock associated with it. The object can get and release it so that only one thread can access object instance variables and methods at any time.

The Lock statement can be said to be implemented through Monitor.Enter() and Monitor.Exit().

When the Lock (lockInstance) {} structure starts executing, call Monitor.Enter (lockInstance) to Lock the lockInstance critical area. When the structure ends executing, call monitor.Exit(lockInstance) to release the lockInstance critical area.

Principle: for any object, the addresses of all methods are placed in the first part of the memory, and an index is placed in the second part, which points to a SyncBlock in the SyncBlock Cache area of the CLR. When you execute Monitor.Enter(object), if the object index value is negative, select a SyncBlock from the SyncBlock Cache and put its address in the object index. This completes the locking with the object as the flag. If other threads want to perform the Monitor.Enter(object) operation again, they will obtain the positive index of the object, and then wait. Until the index becomes negative, that is, call Monitor.Exit (object) to change the index to negative, and the waiting thread starts to execute.

be careful:

1.lock cannot lock Null values, but Null does not need to be released.
2.lock cannot lock the string type, although it is also a reference type, because the string type is "persisted" by the CLR . that is, there is only one instance of any given string in the whole program, and the string with the same content represents the same instance. Therefore, as long as a lock is placed on the string with the same content anywhere in the application process, the string with the same content in the application will be locked. Therefore, it is best to lock the string that will not be retained Have or protected members.

example:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Threading;

public class test
{
    private static object lock_obj = new object();
    string str;
    string path;

    public test(string str, string path)
    {
        this.str = str;
        this.path = path;
    }
    public void Pri()
    {
        lock (str)
        {
            for (int i = 0; i < 10; i++)
            {
                Debug.Log(path + i);
            }
        }
    }
}
public class ApplicationStart : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        string str1 = "ssss";
        string str2 = "ssss";
        test t1 = new test(str1, "This is thread one");
        Thread thread1 = new Thread(new ThreadStart(t1.Pri));
        thread1.Start();
        test t2 = new test(str2, "This is thread two");
        Thread thread2 = new Thread(new ThreadStart(t2.Pri));
        thread2.Start();
    }
}

result:

 

 

 

It can be seen that str1 and str2 are two string variables, but after lock (str1), str2 becomes a critical area and is locked, resulting in lock () {} in thread2 The body is in a waiting state. This corresponds to the statement that as long as a lock is placed on a string with the same content anywhere in the application process, a string with the same content in the application will be locked.
3. The object locked by lock is the memory boundary of a program block
4. The value type cannot be lock ed because the object marked with red ink is released and the value type is not a reference type

5.lock avoids locking objects of public type or not controlled by the program.
For example, if the instance is publicly accessible, lock(this) may be a problem because uncontrolled code may also lock the object. This may lead to a deadlock, that is, two or more threads waiting to release the same object. Locking a common data type (compared to an object) may also cause a problem for the same reason.
When lock(this) is used, the value of the member variable of the class may be changed by methods that are not in the critical zone

Application scenario: it is often used to prevent uncertain exceptions to common variable values caused by multi-threaded operations, so as to ensure the safety of operations.

example:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Threading;

public class test
{
    private static object lock_obj = new object();
    string str;
    string path;

    public test(string str, string path)
    {
        this.str = str;
        this.path = path;
    }
    public void Pri()
    {
        lock (lock_obj)
        {
            for (int i = 0; i < 10; i++)
            {
                Debug.Log(path + i);
            }
        }
    }
}
public class ApplicationStart : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        string str1 = "ssss";
        string str2 = "ssss";
        test t1 = new test(str1, "This is thread one");
        Thread thread1 = new Thread(new ThreadStart(t1.Pri));
        thread1.Start();
        test t2 = new test(str2, "This is thread two");
        Thread thread2 = new Thread(new ThreadStart(t2.Pri));
        thread2.Start();
    }
}

result:

 

 

  It can be seen that after thread thread1 executes lock (object), the object becomes a critical area and is locked. Other threads wait for the lock () {} to complete and the stu is released before starting execution.

--------
Copyright notice: This article is the original article of CSDN blogger "Rong Xia not surnamed Xia". It follows CC 4.0 BY-SA copyright agreement. Please attach the source link of the original text and this notice for reprint.
Original link: https://blog.csdn.net/qq_39025293/article/details/84655433

Posted by Jassal on Tue, 09 Nov 2021 04:02:25 -0800