c#中线程安全的锁定方法和方法调用?
Locking method and calls of method for thread-safety in c#?
我是否应该为线程锁定在 c# 中调用线程安全方法的代码的一部分?
例如:
T Eject (bool? state)
{
lock (this)
{
//somecode
return _objects[i];
}
}
public T TakeNew()
{
return Eject(null);
}
public T Reserve()
{
return Eject(true);
}
或者我应该像这样锁定 return:
lock(this)
{
return Eject(true);
}
如果我锁定所有 Eject(true) 调用,我是否需要锁定方法 Eject 块?我认为,如果我锁定方法和方法调用,它会造成线程死锁。在这种情况下,创建线程安全代码的更好方法是什么?
感谢您的回答!
最佳做法是只锁定尽可能少的代码,因为这样可以最大限度地减少锁争用的机会(从而提高性能和可伸缩性),还可以提高代码的可读性(更容易看出哪些对象受锁保护) .
在您的情况下,仅在 Eject
方法中锁定对 _objects
的访问就足够了(请参阅下面的代码)。锁定方法调用 return Eject(true)
就没有必要了(但如果你这样做,它不会导致死锁)。
另外,使用 this
进行锁定也被认为是错误的做法,因为在某些情况下这会导致死锁。因此专用对象通常存储在封闭的私有或受保护字段中 class 并用于锁定(再次参见下面的代码)。
所以这应该没问题:
class Foo<T>
{
// Dedicated object instance used for locking
private Object m_MyLock = new Object();
T Eject(bool? state)
{
lock (m_MyLock)//You typically use the same locking object everywhere within the class
{
//somecode
return _objects[i];
}
}
string SomeOtherMethod()//Some other method that needs to be threadsafe too
{
lock (m_MyLock)//You typically use the same locking object everywhere within the class
{
return _objects[i].ToString();
}
}
public T TakeNew()
{
return Eject(null);
}
public T Reserve()
{
return Eject(true);
}
}
编辑:
澄清 OP 的评论:您不应为每个锁创建新的锁定对象。您通常在 class 中使用相同的锁定对象。当您在 class 中使用 lock(this)
而代码的另一部分 不知道它 时,我正在谈论的死锁情况可能会发生(例如第三方库代码)以这种不幸的方式使用 class 的实例作为锁定对象,导致死锁。这种情况在 Why is lock(this) {…} bad? 中有更好的解释(包括这种情况的示例)。这就是为什么你应该使用你的私有对象(m_MyLock
)进行锁定,因为这样就不会发生这种情况(尽管它不排除其他可能的死锁情况)。
我是否应该为线程锁定在 c# 中调用线程安全方法的代码的一部分?
例如:
T Eject (bool? state)
{
lock (this)
{
//somecode
return _objects[i];
}
}
public T TakeNew()
{
return Eject(null);
}
public T Reserve()
{
return Eject(true);
}
或者我应该像这样锁定 return:
lock(this)
{
return Eject(true);
}
如果我锁定所有 Eject(true) 调用,我是否需要锁定方法 Eject 块?我认为,如果我锁定方法和方法调用,它会造成线程死锁。在这种情况下,创建线程安全代码的更好方法是什么?
感谢您的回答!
最佳做法是只锁定尽可能少的代码,因为这样可以最大限度地减少锁争用的机会(从而提高性能和可伸缩性),还可以提高代码的可读性(更容易看出哪些对象受锁保护) .
在您的情况下,仅在 Eject
方法中锁定对 _objects
的访问就足够了(请参阅下面的代码)。锁定方法调用 return Eject(true)
就没有必要了(但如果你这样做,它不会导致死锁)。
另外,使用 this
进行锁定也被认为是错误的做法,因为在某些情况下这会导致死锁。因此专用对象通常存储在封闭的私有或受保护字段中 class 并用于锁定(再次参见下面的代码)。
所以这应该没问题:
class Foo<T>
{
// Dedicated object instance used for locking
private Object m_MyLock = new Object();
T Eject(bool? state)
{
lock (m_MyLock)//You typically use the same locking object everywhere within the class
{
//somecode
return _objects[i];
}
}
string SomeOtherMethod()//Some other method that needs to be threadsafe too
{
lock (m_MyLock)//You typically use the same locking object everywhere within the class
{
return _objects[i].ToString();
}
}
public T TakeNew()
{
return Eject(null);
}
public T Reserve()
{
return Eject(true);
}
}
编辑:
澄清 OP 的评论:您不应为每个锁创建新的锁定对象。您通常在 class 中使用相同的锁定对象。当您在 class 中使用 lock(this)
而代码的另一部分 不知道它 时,我正在谈论的死锁情况可能会发生(例如第三方库代码)以这种不幸的方式使用 class 的实例作为锁定对象,导致死锁。这种情况在 Why is lock(this) {…} bad? 中有更好的解释(包括这种情况的示例)。这就是为什么你应该使用你的私有对象(m_MyLock
)进行锁定,因为这样就不会发生这种情况(尽管它不排除其他可能的死锁情况)。