• Lock Statement And Thread Synchronization


    The lock keyword marks a statement block as a critical section by obtaining the mutual-exclusion lock for a given object, executing a statement, and then releasing the lock. The following example includes a lock statement.

        class Account

        {

            decimal balance;

            private Object thisLock = new Object();

     

            public void Withdraw(decimal amount)

            {

                lock (thisLock)

                {

                    if (amount > balance)

                    {

                        throw new Exception("Insufficient funds");

                    }

                    balance -= amount;

                }

            }

    }

     

     

    Remarks

    The lock keyword ensures that one thread does not enter a critical section of code while another thread is in the critical section. If another thread tries to enter a locked code, it will wait, block, until the object is released.

    The section Threading (C# and Visual Basic) discusses threading.

    The lock keyword calls Enter at the start of the block and Exit at the end of the block. A ThreadInterruptedException is thrown if Interrupt interrupts a thread that is waiting to enter a lock statement.

    In general, avoid locking on a public type, or instances beyond your code's control. The common constructs lock (this), lock (typeof (MyType)), and lock ("myLock") violate this guideline:

    ·         lock (this) is a problem if the instance can be accessed publicly.

    ·         lock (typeof (MyType)) is a problem if MyType is publicly accessible.

    ·         lock("myLock") is a problem because any other code in the process using the same string, will share the same lock.

    Best practice is to define a private object to lock on, or a private static object variable to protect data common to all instances.

    Example

     

        //using System.Threading;

     

        class ThreadTest

        {

            public void RunMe()

            {

                Console.WriteLine("RunMe called");

            }

     

            static void Main()

            {

                ThreadTest b = new ThreadTest();

                Thread t = new Thread(b.RunMe);

                t.Start();

            }

        }

    // Output: RunMe called

     

    The following sample uses threads and lock. As long as the lock statement is present, the statement block is a critical section and balance will never become a negative number.

      // using System.Threading;

     

        class Account

        {

            private Object thisLock = new Object();

            int balance;

     

            Random r = new Random();

     

            public Account(int initial)

            {

                balance = initial;

            }

     

            int Withdraw(int amount)

            {

     

                // This condition never is true unless the lock statement

                // is commented out.

                if (balance < 0)

                {

                    throw new Exception("Negative Balance");

                }

     

                // Comment out the next line to see the effect of leaving out

                // the lock keyword.

                lock (thisLock)

                {

                    if (balance >= amount)

                    {

                        Console.WriteLine("Balance before Withdrawal :  " + balance);

                        Console.WriteLine("Amount to Withdraw        : -" + amount);

                        balance = balance - amount;

                        Console.WriteLine("Balance after Withdrawal  :  " + balance);

                        return amount;

                    }

                    else

                    {

                        return 0; // transaction rejected

                    }

                }

            }

     

            public void DoTransactions()

            {

                for (int i = 0; i < 100; i++)

                {

                    Withdraw(r.Next(1, 100));

                }

            }

        }

     

        class Test

        {

            static void Main()

            {

                Thread[] threads = new Thread[10];

                Account acc = new Account(1000);

                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].Start();

                }

            }

    }

  • 相关阅读:
    redis搭建集群并用TreeSoft管理
    使用windows任务计划程序自动清除C盘缓存文件
    深入理解JavaScript事件循环机制
    redux源码解读(二)
    redux源码解读(一)
    create-react-app源码解读之为什么不搞个山寨版的create-react-app呢?
    深入理解CSS系列(二):为什么height:100%不生效?
    深入理解CSS系列(一):理解CSS的盒子模型
    搭建一个交互式的前端构建环境.md
    实习这件小事(一位大四狗的前端实习经历)
  • 原文地址:https://www.cnblogs.com/SFAN/p/2160872.html
Copyright © 2020-2023  润新知