这是 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;
}
}
}
我所说的“适当”是指,如果我想打电话
MyProperty.Field1 = 2;
或者其他什么,当我进行更新时该字段会被锁定吗?是由 equals 运算符在“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;
}
}
}
这或多或少只是确保我只能访问副本,这意味着如果我让两个线程同时调用“get”,它们每个都会以相同的 Field1 值开始(对吗?)。有没有一种方法可以对有意义的属性进行读写锁定?或者我应该限制自己锁定函数部分而不是数据本身?
只是为了让这个示例有意义:MyObject 是一个异步返回状态的设备驱动程序。我通过串行端口向它发送命令,然后设备在自己的最佳时间内响应这些命令。现在,我有一个线程轮询其状态(“你还在吗?你能接受命令吗?”),一个等待串行端口响应的线程(“刚刚得到状态字符串 2,一切都很好”) ),然后是 UI 线程,它接受其他命令(“用户希望你做这件事。”)并发布来自驱动程序的响应(“我刚刚完成了这件事,现在用它更新 UI”)。这就是为什么我想锁定对象本身,而不是对象的字段;这将是大量的锁、a 和 b,并非此类的每个设备都具有相同的行为,只是一般行为,因此如果我对锁进行个性化,我必须编写大量单独的对话框。
不,您的代码不会锁定对从返回的对象的成员的访问MyProperty
。它只锁MyProperty
itself.
您的示例用法实际上是将两个操作合二为一,大致相当于:
// object is locked and then immediately released in the MyProperty getter
MyObject o = MyProperty;
// this assignment isn't covered by a lock
o.Field1 = 2;
// the MyProperty setter is never even called in this example
简而言之 - 如果两个线程访问MyProperty
同时,getter 会短暂阻塞第二个线程,直到将对象返回给第一个线程,but然后它也会将该对象返回给第二个线程。然后,两个线程都将拥有对该对象的完整、未锁定的访问权限。
编辑以回应问题中的更多细节
我仍然不能 100% 确定您要实现的目标,但如果您只想对对象进行原子访问,那么您不能对对象本身进行调用代码锁定吗?
// quick and dirty example
// there's almost certainly a better/cleaner way to do this
lock (MyProperty)
{
// other threads can't lock the object while you're in here
MyProperty.Field1 = 2;
// do more stuff if you like, the object is all yours
}
// now the object is up-for-grabs again
并不理想,但只要对对象的所有访问都包含在lock (MyProperty)
那么这种方法将是线程安全的。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)