当多个线程同时访问共享区时,就会产生线程安全问题。 例如:
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; } }

|