gpt4 book ai didi

c# - 通过 try 中的 lock 锁定资源。这是错的吗?

转载 作者:IT王子 更新时间:2023-10-29 04:37:47 26 4
gpt4 key购买 nike

在 try block 中使用 lock 有什么问题吗?我记得在某处读到我们应该始终尝试在 try block 中放置最少量的代码,并在内部使用 try-finally block 锁定自身,你们看到这里有什么问题了吗?我需要处理这个锁中的代码这一事实 block 可以抛出异常

try  
{
lock(syncblk)
{
// do some processing
}

}
catch(Exception e)
{
// do something with exception
}

最佳答案

I need to deal with the fact that the code within that lock block can throw exception

这就是你的问题。这是一个可怕的情况。

你为什么首先要锁定?通常你锁定某些东西的原因是因为你想实现以下逻辑:

  • 锁上门
  • 弄得一团糟
  • 清理干净
  • 打开门

如果你这样做,那么任何尊重锁着门的人都不会看到这个烂摊子。

例如,您可能希望以线程安全的方式交换变量“left”和“right”的值,因此您:

  • 拿锁
  • 将left变量读入tempLeft
  • 将正确的变量读入tempRight
  • 将tempLeft写入right
  • 我们刚刚弄得一团糟; 'right' 的原始值丢失了
  • 将tempRight写到left
  • 我们清理了烂摊子,世界又恢复了正常
  • 释放锁

现在假设在制造困惑后抛出一个异常。怎么了? 我们直接跳到解锁,把困惑留给另一个线程看

这就是为什么您应该永远不要在锁内抛出异常;它完全违背了锁的目的!锁的全部意义在于确保除了负责清理困惑的线程之外的所有线程始终观察到状态是一致的。

如果您有一个可以从锁中抛出的异常,最好的办法就是摆脱这种可怕的情况。如果您不能这样做,那么请确保您可以 (1) 在异常逃脱锁定后立即完全销毁该进程,这样您造成的困惑就不会导致数据丢失或其他伤害——执行 FailFast 和从轨道上对进程进行核爆,这是唯一可以确定的方法——或者 (2) 编写回滚代码来撤消您在 锁定退出之前尝试的任何操作;也就是收拾残局恢复原状。

如果后者是您的策略,那么不要将 try block 放在 锁之外;它在那里没用,因为即时控制通过异常离开锁,另一个线程可能会崩溃并死掉,因为你留下的困惑暴露给它。将处理异常的尝试放在内部锁中:

lock(whatever)
{
try
{
MakeAMess();
}
finally
{
CleanItUp();
// Either by completing the operation or rolling it back
// to the pre-mess state
}
}

如果您有很强的可靠性要求,那么处理可能引发异常的锁定关键部分是一项极其困难的编程任务,最好留给专家;如果您经常遇到这种情况,您可能会考虑使用 constrained execution region

关于c# - 通过 try 中的 lock 锁定资源。这是错的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5997360/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com