2013-03-21 113 views
1

假设通用类型为每个类型的组合创建单独的静态字段实例,如果我想要在所有类型中都有一个静态字段,这是一个有效的模式吗?适用于泛型类中静态字段的解决方法?

public class BaseClass 
{ 
    public static int P = 0; 
} 

public class ChildClass<T> : BaseClass 
{ 
    public static int Q = 0; 

    public void Inc() 
    { 
     // ChildClass<int> will have a different "Q" than ChildClass<double> 
     Interlocked.Increment(ref Q); 
     // all types of ChildClass will increment the same P 
     Interlocked.Increment(ref P); 
    } 
} 

这种方法有什么不安全的吗?我的玩具示例有效,但我只是想确保没有可怕的副作用,线程后果等。:)

+3

只有真正的不安全部分是增量(现在是这样),它不会是线程安全的。编辑:另外,我假设你想控制获取/设置访问(你希望它是公开可设置的,或者只在'Inc'方法内私下增加?) – 2013-03-21 23:53:54

+0

哈哈好点。我的例子不得不不小心。假设互锁的东西或其他请 – 2013-03-21 23:56:37

+0

我正在处理的实际问题是,我想要一个单线程安全队列,但类添加到这个内部队列的东西是通用的。所以“价值”不会公开设定。 – 2013-03-21 23:58:21

回答

4

您可以使用Interlocked.Increment获取更多线程安全代码。

public void Inc() 
{ 
    Interlocked.Increment(ref Q); // ChildClass<int> will have a different "Q" than ChildClass<double> 
    Interlocked.Increment(ref P); // all types of ChildClass will increment the same P 
} 

或纯老lock

public class BaseClass 
{ 
    protected static int P = 0; 
    protected static object pLock = new object(); 
} 

public class ChildClass<T> : BaseClass 
{ 
    private static int Q = 0; 
    private static object qLock = new object(); 

    public void Inc() 
    { 
     lock(qLock) 
     { 
      qLock++; 
     } 

     lock(pLock) 
     { 
      qLock++; 
     } 
    } 
} 

注意:每次T会有不同ChildClass<T>.Q,但只有将永远是一个BaseClass.P。这意味着你必须使用单独的锁对象来处理QP(技术上你用来锁定的任何东西都可以用来锁定所有的Q,但这可能不是你想要做的)。

+0

感谢您的回答,但问题是更多关于继承/奇异的静态字段,不是真的任何与int的实际递增。我会用你的互锁代码更新我的问题。 – 2013-03-22 00:01:10

2

你的模式是有效的,没有问题。有作为静态继承没有这样的事情,但你可以访问任何类型的静态成员,你通常会(前提是你的派生类中可见,如不private)就像:

BaseClass.P = 10; 
ChildClass<string>.Q = 20; 

的C#规范指出,对32位整数(即int)的单个读取或写入是原子,这意味着它们可以在单个指令内完成,并且永远不会使另一个线程看到半写入变量。布尔,焦炭,字节,为sbyte,短,USHORT,UINT,整数,浮点,和引用类型:

12.5变量引用

读取和下列数据类型的写入应原子的原子性。另外,在前面列表中读取和写入具有基础类型的枚举类型也应该是原子的。其他类型(包括long,ulong,double和decimal)以及用户定义类型的读取和写入不必是原子的。

当然,阅读写不保证是原子的。例如,递增一个变量的值需要它被读取然后写入,这就是Interlocked methods发挥作用的地方。顺便说一下,您可能知道,只有一个P静态变量,但是有多少个Q静态变量,因为您的类型的不同通用实例为ChildClass<T>