实例构造函数设置一个静态成员,它是否是线程安全的?

我正在重新考虑一些代码,并且想知道在实例构造函数中使用lock

 public class MyClass { private static Int32 counter = 0; private Int32 myCount; public MyClass() { lock(this) { counter++; myCount = counter; } } } 

请确认

  1. 实例构造函数是线程安全的。
  2. lock语句阻止访问该代码块,而不是静态“计数器”成员。

如果原始程序员的意图是让每个实例知道它的’count’,我将如何同步访问’counter’成员以确保另一个线程不是新的MyClass并在此之前更改计数它的数量?

仅供参考 – 此课程不是单身人士。 实例必须只知道它们的编号。

@ajmastrean

我并不是说你应该使用单例模式本身,而是采用封装实例化过程的方法。

  • 使构造函数私有。
  • 创建一个返回类型的静态实例方法。
  • 在静态实例方法中,在实例化之前使用lock关键字。
  • 实例化该类型的新实例。
  • 增加计数。
  • 解锁并返回新实例。

编辑

我发生了一个问题,如果你怎么知道计数何时下降? ;)

再次编辑

考虑一下,你可以在析构函数中添加代码,调用另一个静态方法来递减计数器:D

如果你只是增加一个数字,那就有一个特殊的类(Interlocked)就是这样…

http://msdn.microsoft.com/en-us/library/system.threading.interlocked.increment.aspx

Interlocked.Increment方法

增加指定变量并将结果存储为primefaces操作。

 System.Threading.Interlocked.Increment(myField); 

有关线程最佳实践的更多信息……

http://msdn.microsoft.com/en-us/library/1c9txz50.aspx

我猜这是针对单身模式或类似的东西。 你想要做的不是锁定你的对象,而是在修改它时锁定计数器。

 private static int counter = 0; private static object counterLock = new Object(); lock(counterLock) { counter++; myCounter = counter; } 

因为您当前的代码有点多余。 特别是在构造函数中,只有一个线程可以调用构造函数,这与可以跨线程共享并可以从任何共享线程访问的方法不同。

从我可以告诉您的代码中,您试图在创建对象时为对象提供当前计数。 因此,使用上面的代码,计数器将被锁定,而计数器将在本地更新和设置。 所以其他所有构造函数都必须等待计数器被释放。

您可以使用另一个静态对象来锁定它。

 private static Object lockObj = new Object(); 

并在构造函数中锁定此对象。

 lock(lockObj){} 

但是,我不确定是否存在因.NET的编译器优化而应该处理的情况,例如java的情况

最有效的方法是使用Interlocked增量操作。 它将递增计数器并立即返回静态计数器的新设置值(primefaces地)

 class MyClass { static int _LastInstanceId = 0; private readonly int instanceId; public MyClass() { this.instanceId = Interlocked.Increment(ref _LastInstanceId); } } 

在您的原始示例中,lock(this)语句将不具有所需的效果,因为每个单独的实例将具有不同的“this”引用,因此多个实例可以同时更新静态成员。

从某种意义上说,构造函数可以被认为是线程安全的,因为在构造函数完成之前,对正在构造的对象的引用是不可见的,但这对保护静态变量没有任何帮助。

(Mike Schall先把互锁位置)

我想如果你修改Singleton模式以包含一个计数(显然使用线程安全的方法),你会没事的:)

编辑

废话我不小心删了!

我不确定实例构造函数是否线程安全的,我记得在设计模式书中读到这个,你需要确保在实例化过程中锁定到位,纯粹是因为这个..

@Rob

仅供参考,此类可能不是单身,我需要访问不同的实例。 他们必须简单地维持一个计数。 您将改变单身模式的哪一部分来执行“计数器”递增?

或者你是否建议我公开一个静态方法来构造阻塞对代码的访问,该代码增加并用锁读取计数器。

 public MyClass { private static Int32 counter = 0; public static MyClass GetAnInstance() { lock(MyClass) { counter++; return new MyClass(); } } private Int32 myCount; private MyClass() { myCount = counter; } }