this关键字作用,violate用法

写这个博客也是因为本人至今为止还不充分理解voliate关键字,所以有应用错误。 我希望同样不懂的朋友能一起踩坑。 另外,欢迎从上帝的观点来看清楚的大人物指出正文的不恰当之处。

先说一下自己对voliate的理解,voliate可以通过内存屏障禁止指令排序,保证可视性,但不能保证同时安全性。 禁止指令排序当然主要阐述如何保证可见性和不能保证同时安全性的理由。

首先,要了解线程如何更改变量a的值,有三个步骤。

第一步是将a的值从主内存读取到线程的工作内存中。

在步骤2中,在工作存储器中更改a。

在第3步中,将a的值返回主存储器。

用voliate限定的变量在写入操作时处理器增加一个Lock指令,Lock指令将修改后的值直接写入主存储器。 同时,禁用缓存在其他线程工作内存中的a的值。 这两点保证了可视性。 我所理解的可视性是所有线程在修改a之前的a值与主内存一样匹配。

举个板栗,如果两个thread同时操作voliate限定变量a,则thread1和thread2都将a的值从主存储器读入工作存储器后,thread2修改a后,thread1的工作存储器内此时,thread1想修改a来发现自己工作内存中的a,喜欢在日常的voliate应用场景中修饰全局变量,这样可以避免该全局变量的同时问题,但事实并非如此。

因为voliate不能把不是原子的操作变成原子。 原子操作是指该操作在执行中不受其他操作的影响。 在上例中变更变量a的值不是原子性的操作。 因为这个操作有三个步骤。

刚才的例子更能理解。 如果thread2在第一步和第二步之间更改了a的值,则除了thread2更改的a之外,还必须更改thread1。 也就是说,thread1的操作结果受其他线程的影响。 积分来了! voliate可以保证thread1的操作结果正确,但不能阻止thread2影响thread1的操作结果。 这意味着voliate不能使一个非原子操作成为原子,但可以是锁定(其变量只能同时由一个线程操作)或CAS无锁定,这是题外话。

说了这么多,还没说为什么voliate不能保证同时安全。 看看场景,还是上面的例子,thread1说在第一步和第二步之间thread2修改了a。 此时,由于voliate棒的一系列骚动,thread1在执行第二步真正去修正a时得到的还是最新的thread2修正后更新主存储器的值。 但是,如果thread1在步骤2和步骤3之间thread2修改了a! 此时,thread1已经修改完a,准备返回主内存。 在这里大家不要和我一样头疼。 以前,我还以为如果thread2将a修改回主内存,thread1工作内存中的a值会无效。 thread1已经修改完毕后,不会再去主内存读取a的值再修改一次。 那就是现在,刚修正的a的值也返回到主存储器。 啊,吼,这样很快就会出问题的。 这就是voliate不能保证原子性,也就是说不能保证同时安全的理由。

Published by

风君子

独自遨游何稽首 揭天掀地慰生平

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注