KAI*_*KAI 5 .net c# multithreading
我遇到过这样的情况,当我的重写ToString()方法将使用实例的集合之一时。
public override string ToString()
{
string returnStr = "testString";
lock (_sync)
{
returnStr = $"{returnStr}: {string.Join(",", _testList)}"; // where _testList is a List<string> in the class's scope
}
return returnStr;
}
Run Code Online (Sandbox Code Playgroud)
由于我们谈论的是多线程应用程序,我想知道,因为我必须lock()在ToString()方法的主体内部使用,以避免在生成返回字符串时修改集合。当我对集合进行修改时_sync,当然会锁定同一个对象 ( )。
但是,这个方法也被其他几个进程使用,比如 Visual Studio 的调试器,谁知道还有什么,因为这个方法是从Object类本身继承的。
例如:我担心它可能会在幕后更频繁地被调用(由框架或其他任何东西),并且必须使用锁定(这可能导致性能损失),或者它可能会在我调试时导致死锁在糟糕的时刻。
问题:
我是否应该关心这种情况,因为它可能会导致问题,还是可以在内部ToString()(以及从 .net 类型继承的其他方法中)使用对象锁定?
是否有更好的替代解决方案来实现同样的目标?
注意:我正在考虑在每次修改时从集合中生成所需的字符串(在锁内,在那里被操作),所以我准备好在ToString()方法本身中连接集合的字符串格式。我想这对性能会更好,因为 的过程string.Join()不必在每次调用时都运行ToString(),但我真的很想知道更多关于这种情况的信息。
谢谢!
ToString对于线程安全,没有特殊的规则。线程安全是程序的全局属性。您必须了解并控制并发访问数据的所有内容。
如果有机会ToString与其访问的数据写入同时发生,则必须进行适当的同步。List在存在并发写入的情况下读取数据尤其不安全。
由于您的关键区域内部ToString仅使用一把锁并且不会阻塞,因此死锁的风险很小。一旦进入锁,就保证最终能够退出。一般来说,这是一个很好的锁定设计原则。
也许您可以利用无锁模式,例如不可变集合?或者也许您可以使整个对象不可变。