按事理来说结不雅是10000,然则运行下很可能是个小于10000的值。有人可能会说volatile不是包管了可见性啊,一个线程对inc的修改,别的一个线程应当急速看到啊!可是这里的操作inc++是个复合操作啊,包含攫取inc的值,对其自增,然后再写回主存。 假设线程A,攫取了inc的值为10,这时刻被壅塞了,因为没有对变量进行修改,触发不了volatile规矩。 线程B此时也读读inc的值,主存里inc的值依旧为10,做自增,然后急速就被写回主存了,为11。 此时又轮到线程A履行,因为工作内存里保存的是10,所以持续做自增,再写回主存,11又被写了一遍。所以固然两个线程履行了两次increase(),结不雅却只加了一次。
有人说,volatile不是会使缓存行无效的吗?然则这里线程A攫取到线程B也进行操作之前,并没有修改inc值,所以线程B攫取的时刻,照样读的10。 又有人说,线程B将11写回主存,不会把线程A的缓存行设为无效吗?然则线程A的攫取操作已经做过了啊,只有在做攫取操作时,发明本身缓存行无效,才会去读主存的值,所以这里线程A只能持续做自增了。
8.finalize()原则:一个对象的初始化完成先行产生于它的finalize()办法的开端
- 第1条规鞭挞打击度榜样次序规矩是说袈溱一个线程里,所有的操作都是按次序的,然则在JMM里其实只要履行结不雅一样,是许可重排序的,这边的happens-before强调的重点也是单线程履行结不雅的┞俘确性,然则无法包管多线程也是如斯。
- 第2条规矩监督器规矩其实也好懂得,就是在加锁之前,肯定则个锁之前已经被释放了,才能持续加锁。
- 第3条规矩,就实用到所评论辩论的volatile,如不雅一个线程先去写一个变量,别的一个线程再去读,那么写入操作必定在读操作之前。 第4条规矩,就是happens-before的传递性。 后面几条就不再一一赘述了。
综上所述,在这种复合操作的情景下,原子性的功能是保持不了了。然则volatile在膳绫擎那种设置flag值的例子里,因为对flag的读/写操作都是单步的,所以照样能包管原子性的。 要想包管原子性,只能借助于synchronized,Lock以及并发包下的atomic的原子操作类了,即对根本数据类型的 自增(加1操作),自减(减1操作)、以及加法操作(加一个数),减法操作(减一个数)进行了封装,包管这些操作是原子性操作。
面试官:说的还可以,那你知道volatile底层的实现机制?
面试官: 你在哪里会应用到volatile,举两个例子呢?
1.状况量标记,就如膳绫擎对flag的标记,我从新提一下:
- int a = 0;
- volatile bool flag = false;
- public void write() {
- a = 2; //1
- flag = true; //2
- }
- public void multiply() {
- if (flag) { //3
- int ret = a * a;//4
- }
- }
- i = 2;
- j = i;
- i++;
- i = i + 1;
这种对变量的读写操作,标记为volatile可以包管修改对线程急速可见。比synchronized,Lock有必定的效力晋升。 2.单例模式的实现,典范的双重检查锁定(DCL)
- class Singleton{
- private volatile static Singleton instance = null;
- private Singleton() {
- }
- public static Singleton getInstance() {
- if(instance==null
推荐阅读
年前最后一场技巧盛宴 | 1月27日与京东、日记易技巧大年夜咖畅聊智能化运维成长趋势! ELF Binary Image Mapped Into MemoryKernel/User Memory Split内存治理是操作体系的核心义务;它对法>>>详细阅读
地址:http://www.17bianji.com/lsqh/40382.html
1/2 1