使用lock确保线程安全

类别:.NET开发 点击:0 评论:0 推荐:

当多个线程同时访问共享区时,就会产生线程安全问题。
例如:

using System;
using System.Threading;

class Account
{
 int balance;

 Random r = new Random();

 public Account(int initial)
 {
  balance = initial;
 }

 int Withdraw(int amount)
 {


  if (balance < 0)
  {
   throw new Exception("Negative Balance");
  }

  // Comment out the next line to see the effect of leaving out
  // the lock keyword:

  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; 
  }

 }

 public void DoTransactions()
 {
  for (int i = 0; i < 100; i++)
  {
   Withdraw(r.Next(1, 100));
  }
 }
}

class Test
{
 public static void Main()
 {
  Thread[] threads = new Thread[10];  //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();
  }
 }
}

程序改为,即可:
using System;
using System.Threading;

class Account
{
 int balance;

 Random r = new Random();

 public Account(int initial)
 {
  balance = initial;
 }

 int Withdraw(int amount)
 {

  // This condition will never be 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 (this)
  {
   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
{
 public 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();
  }
 }
}

这个就像版本控制中的原理。lock也可以解决singleton中的多线程不安全问题。

这里给出一个懒人模式的singleton的线程安全代码:

public sealed class SingletonTest

{
        private SingletonTest()
        {
                //TODO:一些初始化
        }
         //m_instance申明为volatile则,当变量申明完成后才能访问。
        private static volatile SingletonTest m_instance = null;  
       
        private static Object sync = new Object();
        public static SingletonTest createInstance()
        {
                if(m_instance == null)
                {
                        lock(sync)
                        {
                                m_instance = new SingletonTest();
                        }
                }
                return m_instance;
        }
}


本文地址:http://com.8s8s.com/it/it42868.htm