线程不安全与线程安全示例
2018-01-26 11:38
423 查看
线程不安全与线程安全 示例代码:
class Program { static void Main(string[] args) { Console.WriteLine("Incorrect counter"); var c = new Counter(); var t1 = new Thread(() => TestCounter(c)); var t2 = new Thread(() => TestCounter(c)); var t3 = new Thread(() => TestCounter(c)); t1.Start(); t2.Start(); t3.Start(); t1.Join(); t2.Join(); t3.Join(); Console.WriteLine("Total count: {0}",c.Count); Console.WriteLine("--------------------------"); Console.WriteLine("Correct counter"); var c1 = new CounterWithLock(); t1 = new Thread(() => TestCounter(c1)); t2 = new Thread(() => TestCounter(c1)); t3 = new Thread(() => TestCounter(c1)); t1.Start(); t2.Start(); t3.Start(); t1.Join(); t2.Join(); t3.Join(); Console.WriteLine("Total count: {0}", c1.Count); Console.ReadKey(); } static void TestCounter(CounterBase c) { for (int i = 0; i < 100000; i++) { c.Increment(); c.Decrement(); } } class Counter : CounterBase { public int Count { get; private set; } public override void Increment() { Count++; } public override void Decrement() { Count--; } } class CounterWithLock : CounterBase { private readonly object _syncRoot = new Object(); public int Count { get; private set; } public override void Increment() { lock (_syncRoot) { Count++; } } public override void Decrement() { lock (_syncRoot) { Count--; } } } abstract class CounterBase { public abstract void Increment(); public abstract void Decrement(); } }
线程不安全与线程安全 执行结果:
线程不安全与线程安全 工作原理:
当主程序启动时,创建了一个Counter类的对象。该类定义了一个可以递增和递减的简单的计数器。然后我们启动了三个线程。这三个线程共享同一个counter实例,在一个周期中进行一次递增和一次递减。这将导致不确定的结果。如果运行程序多次,则会打印出多个不同的计数器值。结果可能是0,但大多数情况下则不是0。这是因为Counter类并不是线程安全的。当多个线程同时访问counter对象时,第一个线程得到的counter值10并增加为11。然后第二个线程得到的值是11并增加为12。第一个线程得到counter值12,但是递减操作发生前,第二个线程得到的counter值也是12。然后第一个线程将12递减为11并保存回counter中,同时第二个线程进行了同样的操作。结果我们进行了两次递增操作但是只有一次递减操作,这显然不对。这种情形被称为竞争条件(race condition)。竞争条件是多线程环境中非常常见的导致错误的原因。
为了确保不会发生以上情形,必须保证当有线程操作counter对象时,所有其他线程必须等待直到当前线程完成操作。我们可以使用lock关键字来实现这种行为。
如果锁定了一个对象,需要访问该对象的所有其他线程则会处于阻塞状态,并等待直到该对象解除锁定。
注意:这里的线程安全代码可能会导致严重的性能问题。
相关文章推荐
- 一个线程安全的单例模式示例
- SimpleDateFormat线程不安全示例及其解决方法
- 记录关于HashMap线程不安全示例
- ConcurrencyHashMap的线程安全示例
- C# vb.net 线程中安全的使访问示例
- Java线程之程安全与不安全代码示例
- 线程安全单例模式示例
- java多线程-线程间通信-示例代码-解决安全问题-等待唤醒机制wait()notify()notifyAll()
- 线程安全的定义以及示例说明
- 关于同步线程安全问题
- [转]Java线程安全总结
- Java线程安全和非线程安全
- 函数的线程安全与可重入
- java线程同步最基本的示例
- Java容器的线程安全情况
- windows内存池 一线程分配 一线程释放 无锁 安全?
- HashMap线程不安全相关问题
- 线程安全的循环队列缓冲区
- 创建/销毁线程操作示例
- asp.net中关于静态变量的生命周期和线程安全以及一些类中的定义静态变量的概念