来自网络转载:
学习C#语言时,经常会遇到C#调用instance()试图问题,这里将介绍C#调用instance()试图问题的解决方法。 首先去C#调用instance()试图获得类的实例,instance()成员方法判断该类没有创建唯一实例,于是开始创建实例。由于一些因素,主线程不能马上创建成功,而需要等待一些时间。此时线程1也去调用instance()试图获得该类的实例,因为此时实例还未被主线程成功创建,因此线程1又开始创建新实例。结果是两个线程分别创建了两次实例,对于计数器类来说,就会导致计数的值被重置,与Singleton的初衷违背。解决这个问题的办法是同步。 下面看看本文的计数器的例子的实现: 使用方法一: - using System;
- using System.Threading;
- namespace csPattern.Singleton
- {
- public class Counter
- {
- static Counter uniCounter = new Counter(); //存储唯一的实例。
- private int totNum = 0; //存储计数值。
- private Counter()
- {
- Thread.Sleep(100); //这里假设因为某种因素而耽搁了100毫秒。
- //在非lazy initialization 的情况下, 不会影响到计数。.
- }
- static public Counter instance()
- {
- return uniCounter;
- }
- public void Inc() { totNum ++;} //计数加1。
- public int GetCounter() { return totNum;} //获得当前计数值。
- }
- }
方法一中由于实例一开始就被创建,所以instance()方法无需再去判断是否已经存在唯一的实例,而返回该实例,所以不会出现计数器类多次实例化的问题。 使用方法二: - using System;
- using System.Threading;
- using System.Runtime.CompilerServices;
- namespace csPattern.Singleton
- {
- public class Counter_lazy
- {
- static Counter_lazy uniCounter;
- private int totNum = 0;
- private Counter_lazy()
- {
- Thread.Sleep(100); //假设多线程的时候因某种原因阻塞100毫秒
- }
- [MethodImpl(MethodImplOptions.Synchronized)] //方法的同步属性
- static public Counter_lazy instance()
- {
- if (null == uniCounter)
- {
- uniCounter = new Counter_lazy();
- }
- return uniCounter;
- }
- public void Inc() { totNum ++;}
- public int GetCounter() { return totNum;}
- }
- }
不知道大家有没有注意到instance()方法上方的[MethodImpl(MethodImplOptions.Synchronized)] 语句,他就是同步的要点,他指定了instance()方法同时只能被一个线程使用,这样就避免了线程0调用instance()创建完成实例前线程1就来C#调用instance()试图获得该实例。
|