这是一个关于C#的详细问题。
假设我有一个带有一个对象的类,并且该对象受到锁的保护:
Object mLock = new Object();
MyObject property;
public MyObject MyProperty {
get {
return property;
}
set {
property = value;
}
}
我希望创建一个轮询线程以查询该属性。我还希望该线程偶尔更新该对象的属性,有时用户可以更新该属性,并且用户希望能够查看该属性。以下代码是否能正确锁定数据?Object mLock = new Object();
MyObject property;
public MyObject MyProperty {
get {
lock (mLock){
return property;
}
}
set {
lock (mLock){
property = value;
}
}
}
所谓“properly”,我指的是,如果我想调用
MyProperty.Field1 = 2;
无论是哪种情况,在我进行更新时,该字段是否会被锁定?等于操作符所做的设置是在“get”函数作用域内完成的吗,还是“get”函数(因此是锁定)会先完成,然后是设置,然后调用“set”,从而绕过锁定?
编辑:由于这显然行不通,那么该怎么办?我需要做类似以下的事情吗:
Object mLock = new Object();
MyObject property;
public MyObject MyProperty {
get {
MyObject tmp = null;
lock (mLock){
tmp = property.Clone();
}
return tmp;
}
set {
lock (mLock){
property = value;
}
}
}
这个代码片段使用了一个锁来保证多个线程同时读取某个属性时能够获取到同样的值,但是这只是保证了访问属性的行为正确,而并没有对属性进行加锁保护。如果需要对该属性进行同时读写的保护,应该如何实现呢?是直接对属性进行加锁,还是只对函数部分进行加锁呢?
举个例子说明一下:MyObject是一个异步返回状态信息的设备驱动程序。我通过串口发送命令给它,并等待它响应命令。目前有三个线程,一个轮询设备状态的线程(“你还在吗?可以接受命令吗?”),一个等待串口响应的线程(“刚刚收到状态字符串2,一切正常”),以及一个处理用户输入输出的UI线程(“用户希望你做这件事情”、“我刚刚完成了那件事情,现在更新一下UI”)。因此,我们需要对对象本身进行加锁,而不是对对象中的字段进行加锁。如果对每个字段都进行加锁,那么需要大量的锁,并且由于不同设备具有不同的行为,需要编写大量的单独的对话框。
p
的MyProperty
并同时调用两个线程:p = new MyObject(12)
和p = new MyObject(5)
,那么此访问将被同步。然而,Field1
成员将永远不会被锁定。我很确定这就是你所说的,只是想自己理解一下。 - Snoop