Summary of the usage of the Lock of keyword in c multithreading

  • 2020-06-01 10:56:50
  • OfStack

This article introduces the C# lock keyword. C# provides one keyword, lock, which defines a piece of code as a mutex (critical section), which allows only one thread to enter execution at a time, while other threads must wait.

Each thread has its own resources, but the code area is Shared, meaning that each thread can perform the same function. The problem that this can cause is that several threads execute a function at the same time, resulting in chaotic data and unpredictable results, so we must avoid this situation.

Among them, lock is a relatively easy and simple method of thread synchronization, which is realized by acquiring a mutex for a given object. It guarantees that while one thread is in the critical section of code, another thread won't come in, and it can only wait until that thread object is released, which means that the thread is out of the critical section. Usage:


public void Function()
{
    object lockThis = new object ();
    lock (lockThis)
    {
        // Access thread-sensitive resources.
    }
}

Here is a typical example of using the C# lock keyword, with the usage and use of the C# lock keyword explained in the comments.

using System; 
using System.Threading; 
namespace ThreadSimple
{ 
    internal class Account
    { 
        int balance; // The balance of 
        Random r=new Random(); 
        internal Account(int initial)  
        {  
            balance=initial; 
        }
        internal int Withdraw(int amount) // Take back 
        { 
            if(balance<0) 
            {  
                // if balance Less than 0 Throw an exception   
                throw new Exception("NegativeBalance");// A negative   The balance of  
            } 
            // The following code is guaranteed to change in the current thread balance Before the value is completed  
            // No other thread will execute this code to modify it balance The value of the   
            // As a result, balance The value of theta cannot be less than theta 0 the   
            lock(this)  
            { 
                Console.WriteLine("CurrentThread:"+Thread.CurrentThread.Name); 
                // If there is no lock Keyword protection, then, may be performed at the end if Conditional judgment ( Set up ) after   
                // In addition 1 Four threads execute balance=balance-amount To modify the balance The value of the  
                // This change is not visible to this thread, so it may cause this if The condition is no longer valid  
                // However, the thread continues to execute  balance=balance-amount , so as a result balance May be smaller than the 0 
                if(balance>=amount) 
                { 
                    Thread.Sleep(5);
                    balance=balance-amount; 
                    return  amount; 
                }  else 
                { 
                    return 0;
                    //transactionrejected 
                } 
            }  
        }
        internal void DoTransactions()// A withdrawal transaction 
        {
            for (int i = 0; i < 100; i++)
            {
                Withdraw(r.Next(-50, 100));
            }
        }
    }   
    internal class Test  
    {  
        static internal Thread[] threads=new Thread[10]; 
        public static void Main()  
        {  
            Account acc=new Account(0); 
            for(int i=0;i<10;i++) 
            {  
                Thread t=new Thread(new ThreadStart(acc.DoTransactions));
                threads[i]=t; 
            }
            for (int i = 0; i < 10; i++)
            {
                threads[i].Name = i.ToString();
            }
            for (int i = 0; i < 10; i++)
            {
                threads[i].Start();
                Console.ReadLine();
            }
        }
    } 
}

The parameter of lock must be an object based on the reference type, not the basic type like bool,int, which cannot be synchronized at all. The reason is that the parameter of lock is required to be an object. If int is passed into int, the boxing operation is bound to take place, so every time lock's object will be a new and different object. It is best to avoid public types or object instances that are not controlled by the program, as this can lead to deadlocks. In particular, don't use strings as arguments to lock, because strings are "held in" by CLR, meaning that a given string in the entire application has only one instance, making it more likely to deadlock. It is recommended to use private or protected members that are not "retained" as parameters. Some classes already provide SyncRoot for locked members, such as the Array type, and many other collection types provide SyncRoot as well.

Therefore, the following points should be noted when using lock:
1. If an instance of a class is public, it is better not to lock(this). Because the person using your class may not know that you are using lock, if he or she new an instance and locks that instance, it is very easy to cause a deadlock.

2. If MyType is public, do not lock(typeof(MyType)).

3, never lock1 string.


Related articles: