C# 实例构造函数设置静态成员,它是线程安全的吗?
我正在重新分解一些代码,并想知道如何在实例构造函数中使用C# 实例构造函数设置静态成员,它是线程安全的吗?,c#,.net,multithreading,thread-safety,C#,.net,Multithreading,Thread Safety,我正在重新分解一些代码,并想知道如何在实例构造函数中使用锁 public class MyClass { private static Int32 counter = 0; private Int32 myCount; public MyClass() { lock(this) { counter++; myCount = counter; } } } lock(lockObj
锁
public class MyClass {
private static Int32 counter = 0;
private Int32 myCount;
public MyClass() {
lock(this) {
counter++;
myCount = counter;
}
}
}
lock(lockObj){}
请确认
实例构造函数是线程安全的
lock语句阻止访问该代码块,而不是静态“计数器”成员
如果原始程序员的目的是让每个实例都知道其“计数”,那么我如何同步对“计数器”成员的访问,以确保另一个线程不是新的“正在使用MyClass
,并在设置计数之前更改计数
仅供参考-本课程不是单身学生。实例必须知道它们的数量。我猜这是针对单例模式或类似模式的。您要做的不是锁定对象,而是在修改计数器时锁定计数器
private static int counter = 0;
private static object counterLock = new Object();
lock(counterLock) {
counter++;
myCounter = counter;
}
因为您当前的代码有点多余。特别是在构造函数中,只有一个线程可以调用构造函数,而在方法中,它可以跨线程共享,并且可以从共享的任何线程访问
从代码中我可以看出,您正在尝试为对象提供创建时的当前计数。因此,使用上述代码,计数器将在本地更新和设置时被锁定。因此,所有其他构造函数都必须等待计数器释放。您可以使用另一个静态对象锁定它
private static Object lockObj = new Object();
并将此对象锁定在构造函数中
public class MyClass {
private static Int32 counter = 0;
private Int32 myCount;
public MyClass() {
lock(this) {
counter++;
myCount = counter;
}
}
}
lock(lockObj){}
但是,我不确定是否存在由于.NET
中的编译器优化而应该处理的情况,就像java的情况一样我认为如果您修改包含计数(显然是使用线程安全方法),您会很好:)
编辑
废话我不小心删除了
我不确定实例构造函数是否是线程安全的,我记得在一本设计模式书中读到过这方面的内容,您需要确保在实例化过程中锁定到位,这完全是因为..@
仅供参考,这个类可能不是单例,我需要访问不同的实例。他们必须简单地保持计数。您会将单例模式的哪一部分更改为执行“计数器”递增
或者,您是否建议我公开一个静态方法,用于构造阻止对代码的访问,该代码使用锁递增并读取计数器
public MyClass {
private static Int32 counter = 0;
public static MyClass GetAnInstance() {
lock(MyClass) {
counter++;
return new MyClass();
}
}
private Int32 myCount;
private MyClass() {
myCount = counter;
}
}
@阿贾马斯特里安
我不是说您应该使用singleton模式本身,而是采用它封装实例化过程的方法
i、 e
- 将构造函数设为私有
- 创建一个返回类型的静态实例方法
- 在静态实例方法中,在实例化之前使用lock关键字
- 实例化该类型的新实例
- 增加计数
- 解锁并返回新实例
编辑
我遇到了一个问题,你怎么知道计数什么时候下降了
重新编辑
考虑一下,您可以向析构函数添加代码,调用另一个静态方法来减少计数器:D如果您只是增加一个数字,那么就有一个特殊的类(联锁)用于此
联锁增量法
递增指定变量并将结果存储为原子操作
有关线程最佳实践的更多信息
最有效的方法是使用联锁增量操作。它将一次递增计数器并返回静态计数器的新设置值(原子)
在最初的示例中,lock(this)语句不会产生预期效果,因为每个实例都有不同的“this”引用,因此多个实例可能同时更新静态成员
在某种意义上,构造函数可以被认为是线程安全的,因为在构造函数完成之前,对正在构造的对象的引用是不可见的,但这对保护静态变量没有任何好处
(迈克·沙尔首先得到了联锁位)在构造函数中“锁”是无用的吗?我需要用静态方法锁定对静态“计数器”的访问权限,否则我无法确定还有谁在别处读/写它。@anthony:哪个锁没用?对此
的锁定是无用的,因为没有其他人可以引用此
来锁定它。计数器上的锁(参见上文)是正确的。减少计数器将导致两次分发数字。我认为原始程序员的意图是在创建时保持一个“总数”。计数似乎不用于跟踪与“当前实例”有关的任何内容。实际上,这是示例中最好的部分。ctor中的锁(this)非常好,因为“this”还没有返回给任何其他人,所以死锁发生的范围为零。@Quibblesome,但它不起作用,因为这是问题所在。如果两个线程同时运行new MyClass()
,则一个线程将锁定对其intance的引用,另一个线程将锁定其实例。由于这些是不同的引用,锁不会锁定任何内容,线程也不会互相等待,增量可能会出错。仅供参考,如果要锁定静态字段,可以执行lock(typeof(MyClass)){…}
-请参阅