C# 属性 setter 是临界区吗?
Are C# property setter critical regions?
我的问题很简短:
C# 属性 setter 是临界区,还是我应该自己实现临界区?
下面是一些示例代码:
public class MyClass
{
private int _myProperty;
public int MyProperty
{
get { return _myProperty; }
set
{
//required: start critical section
_myProperty = value;
Do1();
Do2();
//required: end critical section
}
}
protected virtual void Do1()
{
//...
}
protected virtual void Do2()
{
//...
}
}
否,属性不是隐式线程安全。
一个原因是为了非原子操作的线程安全,你需要锁定一个监视器对象(如在lock
语句中)。这是哪个对象,锁定多长时间取决于您的要求。因此,编译器无法自动为您决定。
另一个原因是线程安全具有相当大的性能成本。如果您没有并发代码,这些成本将毫无益处。因此,编译器也不会自动为您做出决定。
(实际上,属性并没有什么特别之处。它们通常作为普通的 get/set 方法实现。语法和工具中的任何特殊处理都只是约定俗成。)
您应该自己实现关键区域,因为上下文切换可能发生在您的线程设置 属性 之后但在您处理 Do1() 和 Do2() 之前。另一个获得处理时间的线程现在可以覆盖您的 属性。
使用锁来保护 setter:
private Object setMyPropertyLock = new Object()
public int MyProperty
{
get { return _myProperty; }
set
{
lock(setMyPropertyLock)
{
_myProperty = value;
Do1();
Do2();
}
}
}
我的问题很简短:
C# 属性 setter 是临界区,还是我应该自己实现临界区?
下面是一些示例代码:
public class MyClass
{
private int _myProperty;
public int MyProperty
{
get { return _myProperty; }
set
{
//required: start critical section
_myProperty = value;
Do1();
Do2();
//required: end critical section
}
}
protected virtual void Do1()
{
//...
}
protected virtual void Do2()
{
//...
}
}
否,属性不是隐式线程安全。
一个原因是为了非原子操作的线程安全,你需要锁定一个监视器对象(如在lock
语句中)。这是哪个对象,锁定多长时间取决于您的要求。因此,编译器无法自动为您决定。
另一个原因是线程安全具有相当大的性能成本。如果您没有并发代码,这些成本将毫无益处。因此,编译器也不会自动为您做出决定。
(实际上,属性并没有什么特别之处。它们通常作为普通的 get/set 方法实现。语法和工具中的任何特殊处理都只是约定俗成。)
您应该自己实现关键区域,因为上下文切换可能发生在您的线程设置 属性 之后但在您处理 Do1() 和 Do2() 之前。另一个获得处理时间的线程现在可以覆盖您的 属性。
使用锁来保护 setter:
private Object setMyPropertyLock = new Object()
public int MyProperty
{
get { return _myProperty; }
set
{
lock(setMyPropertyLock)
{
_myProperty = value;
Do1();
Do2();
}
}
}