假设我有一个包含
的对象A.// ...
private List<double> someList = new List<double>();
// ...
public List<double> SomeList
{
get { lock (this) { return someList; } }
}
// ...
在列表中执行操作是否是线程安全的,如下面的代码所示。知道几个操作可以由不同的线程同时执行。
A.SomeList.Add(2.0);
或
A.SomeList.RemoveAt(0);
换句话说,什么时候释放锁?
答案 0 :(得分:12)
这里没有线程安全。
lock
一旦其保护的块完成,就会在属性返回之前立即释放,因此对Add
ad RemoveAt
的调用不受锁的保护。< / p>
答案 1 :(得分:5)
你在问题中显示的锁定用处不大。
要使列表操作线程安全,您需要实现自己的Add / Remove / etc方法,包装列表中的那些。
public void Add(double item)
{
lock(_list)
{
_list.Add(item);
}
}
此外,最好将列表本身隐藏在班级的消费者中,即将字段设为私有。
答案 2 :(得分:3)
退出lock
语句的正文时会释放锁定。这意味着您的代码不线程安全。
换句话说,您可以确保两个线程不会同时在同一个对象上执行return someList
。但是,当一个线程同时执行Add()
并且另一个线程将执行RemoveAt()
时,肯定有可能执行{{1}},这使得它不是线程安全的。
答案 3 :(得分:2)
当锁内部的代码执行完毕后,锁被释放。 此外,对此进行锁定只会影响对象的当前实例
答案 4 :(得分:1)
好的,只是为了它的地狱 通过使用已经线程安全的体系结构,有一种方法可以使对象线程安全。
例如,您可以将对象设置为单个线程 COM 对象。 COM对象将是线程安全的,但您将支付性能(懒惰的价格而不是管理自己的锁)。
<强> Create a COM Object in C# 强>
答案 5 :(得分:0)
......其他人已经说过,但只是为了使问题正式化......
lock (this) {...}
表示“范围” - 例如像using (){}
- 它只锁定(在本例中为)变量里面的变量。这实际上是一件“好事”:),好像你不能依赖它,整个锁/同步概念将毫无用处,lock (this) { return something; }
是一种矛盾的东西 - 它会返回一些东西,在它返回的同一时刻解锁,“最后,有一种常见的误解,即lock(this)实际上修改了作为参数传递的对象,并以某种方式使其成为只读或不可访问。这是错误的。该对象作为参数传递锁定只是作为一个关键“(这是一个引用)
EventWaitHandle
相当用于同步“远程”代码之间的事物,而另一个代码则触发另一个等等。)