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();

            }

        }

}

 

posted @ 2011-08-31 16:19  sunnyboy  阅读(2423)  评论(0编辑  收藏  举报