多线程环境下,程序真是危机四伏

姿势在不断的更新迭代, 太卷了。

你管这也叫线程安全?

       最近大意了,竟然想将《面试官:实现一个带值变更通知能力的Dictionary》一文中的临界锁只应用到写操作。

内心旁白:读操作又不会修改数据,无论是新值还是旧值,反正能读到。

不过我又快速清醒了,临界锁还真就得这么加。临界锁的目的是保证这一段代码逻辑不会被打断。

假如只应用写锁:

某线程执行到写锁前(刚触发了一次变通通知),这时cpu时间片轮转或抢占, 切换到另外的线程又把这段代码执行了一次(因为字典key-value还没被前线程覆写),这样一次value变更实际执行了两次变更操作,这就悲剧了。


结合之前《你管这叫线程安全?》一文中多线程对于i++i--带来的线程不安全的理解。

你品你细品: 

 本次线程安全是在宏观代码行执行层面, 上次的i++ 是在微观寄存器层面,归根到底让多线程在多核环境下:代码逻辑不能被打断(代码执行节奏可能被打断)。

多线程环境下,程序运行真是危机四伏。

微软官方怎么说?

还没完, 我还从微软官方原子操作[1]找到一段话:

Reads and writes of the following data types are atomic: bool, char, byte, sbyte, short, ushort, uint, int, float, and reference types. In addition, reads and writes of enum types with an underlying type in the previous list are also atomic. Reads and writes of other types, including long, ulong, double, and decimal, as well as user-defined types, are not guaranteed to be atomic. Aside from the library functions designed for that purpose, there is no guarantee of atomic read-modify-write, such as in the case of increment or decrement.

直译起来:
① bool char byte sbyte uint int float 和引用类型上的读写是原子操作;

② 由以上类型定义的枚举类型操作也是原子类型;

③ long ulong double decimal和用户定义类型上的读写不保证是原子操作;

④ 除了库文件本身设计了线程安全,一般况下下都不保证读写是原子操作, 这也包括i++i--

这段文字是不是刷新了某些童靴的认知(包括在下):

1. 以后使用long num=8888;时要留个心眼,你也许会读到long类型的部分字节。2.直译第①点说引用类型的读写是原子操作,第③点说用户类型不保证原子操作,但是大部分的用户类型是引用类型,这不互相矛盾了吗?

我向微软官方提出了我的这个疑问,有兴趣可以关注这个github issue[2]

说说我的看法:

直译第①点中说int,引用类型等读写操作是原子操作:应该想表达的是纯粹的赋值操作, 比如

int a =1;                               //  赋值:线程安全
Student s = new Student {};             // 引用赋值:线程安全
Student  s2= s;                         // 引用赋值:线程安全

针对引用类型Dictionary的其他操作自然不是线程安全的。

依据这个思路, 第①③点就不矛盾了。


That's All, 本文依旧是#线程安全#、#锁# 这两个老生常谈的概念的延续, 我的知识体系也是在不断迭代更新,不断精炼。

我也没想到越挖越深,真的是太卷了,如有不同的看法,请留言交流。

引用链接

[1] 微软官方原子操作: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/variables
[2] github issue: https://github.com/dotnet/csharpstandard/issues/372

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/298261.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

眼见不一定为实!18个神奇的视错觉,看完不相信眼睛系列

全世界只有3.14 % 的人关注了爆炸吧知识来源:普象工业设计小站在家长时间网上冲浪总有时候感觉眼睛出了毛病不信,你看为啥这个明明是个三棱锥怎么突然变成了正方体我是“瞎”了么啊啊啊啊后来,去找了资料才发现这原来是一家幻觉博物馆的展品玩…

怎么用java ee编程_Java EE应用程序入门 - 编程入门网

Java EE应用程序入门时间:2011-07-06 netbeans.org本文将详细介绍使用 EJB 3.0 技术开发企业应用程序的基础知识,而 EJB 3.0 是 Java EE 5 平台的组成部分。本文还将阐述如何通过 EJB 3.0 技术简化开发企业应用程序的流程。本文使用的是 NetBeans IDE 6.0 发行版。先…

vb6 由于超出容量限制 不能创建新事务_分布式限流?你也能轻松玩转(没啥新技术)...

点击蓝色「日拱一兵」关注,持续侦破 Java 技术案件一、什么是限流?为什么要限流?不知道大家有没有做过帝都的地铁,就是进地铁站都要排队的那种,为什么要这样摆长龙转圈圈?答案就是为了限流!因为…

Managing Gigabytes--文本压缩

开门见山,文本压缩可以归纳为两大类, 符号方法和字典方法, 下面分别介绍下: 1)符号方法,symbolwise method普通编码方式是每个字符都采用相同位数编码, 比如asc码, 每个字符都是8位编码。那么现…

Linux学习笔记 1 环境变量 2 vi命令

1 环境变量篇 1.1 修改 查看 生效 系统环境变量 1 涉及系统环境变量的文件 --> .bash_profile --> /etc/profile 2 该文件位置 /root/.bash_profile 3 文件编辑器打开 vi .bash_profile 4 文件末尾加入 JAVA_HOME /usr/share/jdk 1.6.0 PATH $JAVA_HOME/bin:$PA…

一个简单的存储过程

存储过程实现循环取出以特定字符间隔的字符串的单个字符串比如:ab,cdsfd,efdf,owoief,lows实现存储过程后的结果为:abcdsfdefdfowoieflows 这样就可以对这些数据进行循环执行操作 存储过程:if exists(select * from sysobjects where namepro…

基于事件驱动架构构建微服务第8部分:在应用程序上实现事件溯源

原文链接:https://logcorner.com/building-microservices-through-event-driven-architecture-part8-implementing-eventsourcing-on-application/在本文中,我将讨论应用程序上的事件溯源实现。该层围绕领域并实现用例(特定于应用程序的业务规…

我们来聊点成年人的话题!

1 这个话题透漏着成年人都存在的问题,其中心思想行走在道德底线,让人不得不深思,句句入心2 哈哈哈哈哈哈哈哈哈哈哈哈哈画面惊人 图自动漫次元酱3 对不起,我不是你家的鸡,我是一只大鸟!!&#x…

python3 csv读写_在python3中读取、更新和写入更新的CSV文件

我正在创建一个应用程序来本质上充当一个资产数据库,我试图打开一个CSV文件,读取值并相应地更新它们。我看到很多关于如何读写CSV文件的教程,但是我找不到一个详细介绍如何迭代CSV文件和更新单个值的教程。理想情况下,与列表相比&…

js数字相加

las_number Number(ads) Number(abs),转载于:https://www.cnblogs.com/gengaixue/archive/2011/07/08/2100971.html

js获取int类型长度_js代码比较大小前需要把string转换int

今天在写代码时发现一个容易忽略的问题,写下来以供参考这是做的一个验证,设置的最小值minValue不能小于参数本身的最小值min当输入正数的时候都没有问题,但是输入负数时就出现问题了正确设置参数var minValue -30 ,var min -300 ,console.l…

yum安装最新的 LNMP

2019独角兽企业重金招聘Python工程师标准>>> 先添加几个源: rpm -Uvh http://dl.fedoraproject.org/pub/epel/7/x86_64/e/epel-release-7-1.noarch.rpm rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm 1,安装nginx&a…

JavaScript中encodeURI,encodeURIComponent与escape的注意

大家在使用JS提交数据时,尤其是中文的时候,经常会需要将要提交的字符串进行URL编码。在JS中对字符串进行URL编码有好几种方法,encodeURI,encodeURIComponent,还有escape。在我看到的很多代码中escape这个函数用的最多&…

C#新版本风格项目文件(SDK风格项目 SDK-style project)

在VisualStudio中创建NetCore以上版本的项目,使用的都是新版本风格的项目文件。和旧版本.NetFramework版本的项目文件区别:双击项目可直接打开csproj文件进行编辑配置项目文件内容的改变项目属性文件夹图标更改项目引用去除,改成依赖项Nuget包…

史上最丧心病狂的商品定价套路:如何从数学角度,榨干你身上的每一分钱

全世界只有3.14 % 的人关注了爆炸吧知识世上没有精明的买家,只有精明的卖家。的确,卖家的嘴,骗人的鬼。在买与卖的博弈中,没有一个买家可以取胜。别不信,今天就让你见识下“卖家套路终极奥义”。按量定价,是…

python 接口自动化_Python 接口自动化测试

1. 接口基础知识1.1 接口分类接口一般来说有两种,一种是程序内部的接口,一种是系统对外的接口。(1) webservice接口:走soap协议通过http传输,请求报文和返回报文都是xml格式的,我们在测试的时候都要通过工具才能进行调…

工厂模式 Factory

工厂模式 记得一个好友面试的时候,面试官问他,你怎么获得一个类的对象的好友说,new一个啊,的确没错,对象不是new难道还是create... 当然在使用new对象的时候,这段代码也就意味着难以以后的维护和扩展了&…

java定时器写法_java定时器的写法是什么样?

定时器的用法是java核心基础之一,很多特殊功能都需要用到定时器,下面一起来看看定时器是如何编写的吧。示例:一个具备周期性定时(毫秒级);单时刻定时(秒级);多时刻定时(秒级)。后两个时间的设置必须符合“yyyy-MM-ddHH:mm:ss”、“yyyy-MM-dd…

CentOS中vsftp安装、配置、卸载

CentOS中vsftp安装、配置、卸载转载http://www.zjgsq.com/1509.html转载于:https://blog.51cto.com/bbtao/1606816

struts2文件上传

/*** 单文件的上传* author Administrator**/public class FileUploadAction extends ActionSupport {private static final com.opensymphony.xwork2.util.logging.Logger logger LoggerFactory.getLogger(FileUploadAction.class);//上传文件private File upload;//保存路径…