在我的多线程应用程序中,我使用了一些可以由多个实例同时更改的变量。这很奇怪,但它在没有任何problem..but的情况下工作得很好,当然我需要让它成为线程安全的。我刚刚开始学习锁,所以我会优先考虑你的建议:
当客户端连接时,将创建类client,其中每个客户端都有自己的"A“变量。
有时,客户端会像这样调用方法:
Client selectedClient SelectOtherClientClassByID(sentID);
selectedClient.A=5;直到现在,即使5个类同时在做(线程池),这也没有问题,但我在想,给A属性添加锁会怎么样?
像这样:
A {
get { return mA; }
set {
// use lock here for settting A to some value
}
}可以吗?
发布于 2009-10-23 17:50:16
你需要在get和set中使用锁。此锁必须是同一对象。例如:
private object mylock = new object();
public int A {
get {
int result;
lock(mylock) {
result = mA;
}
return result;
}
set {
lock(mylock) {
mA = value;
}
}
}发布于 2009-10-23 18:17:55
锁定对访问器内部属性的访问可能会导致虚假的结果。对于该示例,请查看以下代码:
class C {
private object mylock = new object();
public int A {
get {
int result;
lock(mylock) {
result = mA;
}
return result;
}
set {
lock(mylock) {
mA = value;
}
}
}
}
C obj = new C;
C.A++;(是的,我从第一个答案中复制了它)这里有一个竞争条件!操作"C.A++“实际上需要对A进行两次单独的访问,一次是获取值,另一次是设置更新值。没有任何东西可以确保这两个访问将一起执行,而不会在它们之间进行上下文切换。竞态条件的经典场景!
所以,要当心!将锁放在访问器中并不是一个好主意,锁应该显式获取,就像前面的答案所建议的那样(虽然不一定要使用SyncRoots,但任何对象都可以)。
发布于 2009-10-23 17:53:41
当你所需要的仅仅是设置一个属性时,这是非常罕见的。更常见的情况是,selectedClient.A = 5是一个更大的逻辑运算的一部分,这涉及到几个赋值/求值/等等。在整个运算过程中,你更希望selectedClient处于一致的状态,而不是引入死锁/竞争条件。因此,在Client类中公开SyncRoot属性并从调用代码中锁定该属性会更好:
Client selectedClient = GetClient(...);
lock(selectedClient.SyncRoot)
{
selectedClient.A = 5;
selectedClient.B = selectedClient.A * 54;
}https://stackoverflow.com/questions/1612406
复制相似问题