我注意到,没有人在他们对这个老问题的回答中提到,对异常解除锁定是一件非常危险的事情。是的,C#中的lock语句具有“ finally”语义。当控件正常或异常退出锁时,将释放锁。你们都在说这是一件好事,但这是一件坏事!如果您有一个引发未处理异常的锁定区域,那么正确的做法是在终止有病的进程之前立即终止该进程,该进程会破坏更多的用户数据,而不是释放锁定并继续进行下去。
这样看:假设您有一间浴室,门上有锁,外面有一排人。浴室里的炸弹爆炸,杀死在那里的人。您的问题是“在那种情况下,锁会自动解锁,以便下一个人进入浴室吗?” 是的,它会的。 那不是一件好事。一枚炸弹刚炸进去,炸死了一个人!管道可能已被破坏,房屋的结构已不再健全,那里可能还有炸弹。正确的做法是尽快让所有人离开,并拆除整个房屋。
我的意思是,仔细考虑一下:如果您锁定了代码区域以便从数据结构中读取数据而不在另一个线程上对其进行突变,并且该数据结构中的某些内容引发了异常,则很可能是因为该数据结构腐败了。用户数据现在混乱了;您此时不想尝试保存用户数据,因为那样您将保存损坏的数据。只需终止该过程即可。
如果您锁定了代码区域以便执行变异而又没有另一个线程同时读取状态,并且抛出了变异,那么如果数据以前没有损坏,那么现在肯定是。这正是锁应该防止的情况。现在,等待读取该状态的代码将立即被授予访问损坏状态的权限,并且可能自身崩溃。同样,正确的做法是终止该过程。
无论如何切片,锁中的异常都是一个坏消息。正确的问题不是“如果发生异常,我的锁会被清理吗?” 正确的问题是:“如何确保锁中永远不存在异常?如果存在,那么如何构造程序,以便使突变回滚到以前的良好状态?”