NVIDIA 初创加速计划,免费加速您的创业启动 了解详情
写点什么

C# 4.0“修复了”死锁问题

  • 2009-03-22
  • 本文字数:1085 字

    阅读完需:约 4 分钟

几年前,Eric Lippert 注意到根据同样源代码进行优化构建和非优化构建会导致不同的潜在死锁。这个问题会在 C# 4.0 中被“修复”。“修复”放在引号当中,是因为解决方式也有它自己的问题。

最初的问题可能来自于编译器在把 IL 转化为机器代码的时候,根据你是否打开或关闭优化器和调试器,以非一致的行为插入了 no-op 指令。Lippert 提道:

回想一下,lock(obj){body}实际上就是下面代码的语法:> var temp = obj;

Monitor.Enter(temp);
try { body }
finally { Monitor.Exit(temp); }

这里的问题是,如果编译器在 Monitor.Enter 和受 try 保护的区域之间生成了 no-op 指令,那么运行时就有可能 在 Monitor.Enter 之后和 try 之前抛出线程终止异常。在这样的情形下,finally 不会执行,那么也就产生了程序锁泄漏,程序有可能出现死 锁。如果在非优化和优化构建中不存在差异,就不存在这个问题。

不过。这个解决方案 [译注:C# 4.0 是将 Monitor.Enter() 移入到 try 子句中,并在 Enter 的时候会传递一个引用值,标识锁是否被占用。在 finnally 子句中,会首先判断锁是否被占用,如果被占用,则释放锁。] 也有它自己的问题。据 Eric 说,“保持一致与不一致相比,完全就是五十步笑百步。它仍然存在很大的问 题…这样生成的代码所 [译注:生成的代码是指编译器将 lock 转换为 IL,实际上就相当于使用 Monitor 的语法] 隐含的意义就是认为死锁程序是可能 发生的最糟糕的事情。这种说法未必准确。”

锁的目的是为了保护可变资源,或者换句话说,是为了避免可变资源的多个潜在用户访问资源已被破坏的版本。4.0 版本的现有解决方案并没有包含回滚到原始状态的功能,也没有保证可变资源的完整性。强行进入 lock 语句的 finally 子句、释放锁以及允许访问任意等待 线程(该线程占用了已被破坏的资源),都有可能引发异常。这一解决方案在结果的一致性、降低死锁的可能性和对访问被破坏状态可能付出的代价方面,做出了折 衷。该问题尤其在多线程编程中会存在风险。

这个特定的折衷是对两种糟糕结果的选择:程序死锁,还是不再保护重要资源的状态。所谓“两害相权取其轻”,当我们进行多线程编程时,就必须在多个设计决策与权衡中做出一个选择。

这篇文章反响热烈, 一些开发人员认为这类设计问题不只限于多线程,在“安全锁”和“安全异常”之间也存在不同之处。Lippert 也同意多线程只会让难处理的问题更难,“正 确获得锁仅仅是万里长征的第一步”,你的设计还需要考虑其他各种异常,以及在异常发生后如何处理它们。大量的回复者指出终止线程的危险性,并部分同意 Lippert 所说的“终止异常纯粹就是找死”。

查看英文原文: C# 4.0 “Fixes” Deadlock Issue

2009-03-22 21:522037
用户头像

发布了 254 篇内容, 共 53.6 次阅读, 收获喜欢 2 次。

关注

评论

发布
暂无评论
发现更多内容

一文整理区块链技术为企业带来的九大好处

CECBC

SphereEx 完成近千万美元 Pre-A 轮融资,加速构建新一代数据库生态引擎

SphereEx

开源 融资 ShardingSphere SphereEx 嘉御资本

【量化】量化交易入门系列3:经典的量化交易策略(中)

恒生LIGHT云社区

量化投资 量化交易 量化

今天你的静态变量和静态代码块执行了吗?

华为云开发者联盟

Java 类加载 静态 静态变量 静态代码块

Hive on Spark和Spark sql on Hive,你能分的清楚么

华为云开发者联盟

sql 分布式计算 Sparksql hive on spark 数据源

网络安全好学吗?基础入门篇,NMAP高级使用技巧和漏洞扫描发现

学神来啦

网络安全 渗透测试 kali基础 nmap kali Linux

一文了解区块链如何帮助打击虚假信息

CECBC

面试官:为什么不同返回类型不算方法重载?

王磊

netty系列之:选byte还是选message?这是一个问题

程序那些事

Java Netty 程序那些事 UDT 1月月更

架构营模块八作业

GTiger

架构实战营

「自我检验」熬夜总结50个Vue知识点,全都会你就是神!!!

Sunshine_Lin

面试 Vue 前端 进阶 ES6

什么是Log4Shell?Log4j漏洞解读

龙智—DevSecOps解决方案

log4j Log4j 2 Log4Shell

Java开发之测试框架知识分享

@零度

Java

大数据开发之Hive SQL的优化分享

@零度

大数据 Hive SQL

数据库批量插入这么讲究的么?

秦怀杂货店

Java 数据库 批量插入

测试阻碍交付,如何破解这一难题?

SoFlu软件机器人

nodejs 异步I/O和事件驱动

编程江湖

nodejs

Go 通过 Map/Filter/ForEach 等流式 API 高效处理数据

万俊峰Kevin

微服务 stream go-zero Go 语言

【Golang】浅谈协程并发竞争资源问题

恒生LIGHT云社区

golang 后端 协程 并发 Go 语言

Flink类型系统的根及相关接口

编程江湖

flink

编写Spring MVC控制器的技巧

编程江湖

Spring MVC

EMQ 映云科技入围 Venture50 行业榜单,数字科技企业风向标!

EMQ映云科技

物联网 Venture50

前端开发Vue中的v-指令的使用

@零度

Vue 前端开发

潘娟:Keep open,Stay tuned 开源为我打开的全新世界 | TiDB Hackathon 2021 评委访谈

PingCAP

作业4

施正威

科技驱动经济发展的时代全面到来

CECBC

书单 | 学习数据可视化?看这些书就够了!

博文视点Broadview

带你认识7种云化测试武器

华为云开发者联盟

测试 接口测试 华为云DevCloud 云化测试 Mock 服务

ReactNative进阶(一):ReactNative 学习资料汇总

No Silver Bullet

React Native 1月月更

Kafka原理——Kafka为何如此之快?

Kafka中文社区

10个问题让你快速避开java中的jdbc常见坑

华为云开发者联盟

Java 数据库 JDBC fetchSize Prepared Statement

C# 4.0“修复了”死锁问题_.NET_David West_InfoQ精选文章