这叫线程安全吗?最近粗心,想把《面试官:实现一个带值变更通知能力的Dictionary》一文中的临界锁应用到只写操作上。内心自述:读操作不会修改数据,不管是新值还是旧值,反正都能读到。不过很快又醒悟过来,关键锁还真得加成这样。关键锁的目的是保证这段代码的逻辑不会被打断。如果只使用写锁:一个线程在写锁之前执行(刚刚触发了workaround通知),此时cpu时间片轮转或者抢占,切换到另一个线程再次执行这段代码(因为字典key-value还没有被之前的线程覆盖),这样的值变化实际上执行了两次变化操作,这是一个悲剧。结合之前的文章《你管这叫线程安全?》多线程理解i++和i--带来的线程不安全。你尝你的精品:这个线程安全是在宏代码行执行层面,最后的i++是在微寄存器层面。归根结底,让多线程在多核环境下工作:代码逻辑不能被打断(代码执行节奏可能被打断interrupt)。在多线程环境下,程序运行确实很危险。微软官方怎么说?还没结束。我还从微软官方的原子操作[1]中找到了一段话:以下数据类型的读写是原子的:bool、char、byte、sbyte、short、ushort、uint、int、float、引用类型。此外,在前面列表中具有底层类型的枚举类型的读取和写入也是原子的。其他类型的读取和写入,包括long、ulong、double和decimal,以及用户定义的类型,不保证是原子的。除了为此目的而设计的库函数之外,无法保证原子读-修改-写,例如在递增或递减的情况下。直译:①boolcharbytesbyteuintint对float和引用类型的读写是原子操作;②上述类型定义的枚举类型操作也是原子类型;③longulongdoubledecimal和自定义类型的读写不保证是原子操作;④除了库文件本身,都设计了线程安全。一般情况下,不保证读写都是原子操作。这还包括i++,i--这段文字是不是刷新了部分童靴(包括下面)的认知:1.以后使用long注意num=8888;时,可能会读到一些long类型的字节。2.直译第①点说引用类型的读写是原子操作,第③点说用户类型不保证原子操作,但大多数用户类型都是引用类型。这不是自相矛盾吗?我向微软官方提出了我的问题,有兴趣的可以关注这个githubissue[2]。说说我的看法:在直译点①中说int和引用类型等读写操作是原子操作:应该表达的是纯赋值操作,比如inta=1;//Assignment:thread-safeStudents=newStudent{};//引用赋值:线程安全Students2=s;//引用赋值:线程安全其他对引用类型Dictionary的操作自然不是线程安全的。按照这个思路,①和③点并不矛盾。仅此而已,本文依旧是#threadsafety#和#lock#这两个陈词滥调概念的延续,我的知识体系也在不断迭代更新和完善。
