首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

京东面试题:Java中 ++i 操作是线程安全么?为什么?如何使其线程安全呢?

转载自https://blog.csdn.net/fansunion/article/details/79625510 相关文章 你真的了解volatile关键字吗?...可以参考http://blog.csdn.net/taohuaxinmu123/article/details/24472073中Java虚拟机栈(Java Virtual Machine Stacks...在这三步任何之间都可能会有CPU调度产生,造成i值被修改,造成脏读脏写。 接下来说volatile不能解决这个线程安全问题。因为volatile只能保证可见性,不能保证原子性。...这里还可以比较这两种方式优劣。...因为传统锁机制需要陷入内核态,造成上下文切换,但是一般持有锁时间很短,频繁陷入内核开销太大,所以随着机器硬件支持CAS后,JAVA推出基于compare and set机制AtomicInteger

39210

京东面试题:Java中 ++i 操作是线程安全么?为什么?如何使其线程安全呢?

转载自  相关文章 你真的了解volatile关键字吗?...可以参考http://blog.csdn.net/taohuaxinmu123/article/details/24472073中Java虚拟机栈(Java Virtual Machine Stacks...在这三步任何之间都可能会有CPU调度产生,造成i值被修改,造成脏读脏写。 接下来说volatile不能解决这个线程安全问题。因为volatile只能保证可见性,不能保证原子性。...这里还可以比较这两种方式优劣。...因为传统锁机制需要陷入内核态,造成上下文切换,但是一般持有锁时间很短,频繁陷入内核开销太大,所以随着机器硬件支持CAS后,JAVA推出基于compare and set机制AtomicInteger

39410
您找到你想要的搜索结果了吗?
是的
没有找到

Java volatile修饰符用法及作用详解版

要深刻理解volatile这个关键字用法及作用,需要补充以下知识: 1、               内存访问操作/指令执行操作乱序:假设每个CPU都分别运行着一个会触发内存访问操作程序。...13、           volatile原理和实现机制(下面这段话摘自《深入理解Java虚拟机》): “观察加入volatile关键字和没有加入volatile关键字时所生成汇编代码发现,加入volatile...你可以这样理解:线程1自增操作指令“inc++;”虽然对应了三个子操作,但是这三个子操作是被当作一个整体来执行,也就是说,在当前假设情形,线程2inc变量修改操作只能影响线程1中“inc++.../xrq730/p/7048693.html 就是要你懂Java中volatile关键字实现原理 6、https://blog.csdn.net/bytxl/article/details/50275377...ef8de88b1343 并发关键字volatile(重排序和内存屏障) 10、https://blog.csdn.net/dashuniuniu/article/details/50347149 基于栈虚拟机

34030

JVM之内存模型与线程

(在多核CPU中,每条线程可能运行于不同CPU中,因此每个线程运行时有自己高速缓存(单核CPU来说,其实也会出现这种问题,只不过是以线程调度形式来分别执行)。本文我们以多核CPU为例。)...因为CPU和其他部件进行通信都是通过总线来进行,如果总线加LOCK#锁的话,也就是说阻塞了其他CPU其他部件访问(如内存),从而使得只能有一个CPU能使用这个变量内存。...java还有两个关键字实现可见性: synchronized 和 final: - 同步块可见性: 是由一个变量执行unlock 操作前,必须先把此变量同步回主内存中; - final关键字可见性...前半句是指: 线程内表现为串行语义,后半句是指:指令重排序现象和工作内存与主内存同步延迟现象; **volatile和 synchronized关键字保证了线程间操作有序性:**volatile关键字本身就包含了禁止指令重排序语义...,使用用户线程加轻量级进程混合实现 使用内核线程实现 内核线程(KLT,Kernel-Level Thread):就是直接由操作系统内核内核)支持线程,这种线程由内核来完成线程切换,内核通过操纵调度器对线程进行调度

20710

java架构之路(多线程)JMM和volatile关键字(二)

再就是简单提到了我们volatile关键字,他可以保证我们可见性,也就是说被volatile关键字修饰变量如果产生了变化,可以马上刷到主存当中去。我们接下来看一我们这次博客内容吧。...在这里多提一句就是线程分为内核级线程和用户级线程,我们在java虚拟机内线程一般都为用户级线程,也就是由我们jvm虚拟机来调用我们CPU来申请时间片来完成我们线程操作。...而我们内核级线程是由我们系统来调度CPU来完成,为了保证安全性,一般线程都是由虚拟机来控制。   ...JVM能根据处理器特性(CPU多级缓存系统、多核处理器等)适当机器指令进行重排序,使机器指令能更符合CPU执行特性,最大限度发挥机器性能。   ...,我们可以把代码改为 private static volatile int a = 0, b = 0; 继续来测试,我们发现无论我们运行多久都不会发生我们指令重排现象,也就是说我们volatile关键字可以保证我们有序性

44020

Java编程之伪共享与缓存行填充

如果两个独立线程同时写两个不同值会更糟,因为每次线程缓存行进行写操作时,每个内核都要把另一个内核缓存块无效掉并重新读取里面的数据。...: 场景一:Long变量进行写入,没有缓存行填充,没有volatile关键字。...场景二:Long变量进行写入,有缓存行填充,没有volatile关键字。 场景三:Long变量进行写入,没有缓存行填充,有volatile关键字。...场景四:Long变量进行写入,有缓存行填充,有volatile关键字。...场景三和场景四有volatile关键字就不一样了,这里可以看出volatile关键字一个变量读取和写入性能影响还是比较大,写入耗时是直接写入200多倍,因此volatile关键字怎么用很关键,用到哪些地方也很关键

50530

Memory barrier 简介

编译时内存乱序访问 在编译时,编译器代码做出优化时可能改变实际执行指令顺序(例如 gcc O2 或 O3 都会改变实际执行指令顺序): // test.cpp int x, y, r; void...本例中,我们还可以使用 volatile 这个关键字来避免编译时内存乱序访问(而无法避免后面要说运行时内存乱序访问)。...volatile 关键字能够让相关变量之间在内存访问上避免乱序,这里可以修改 x 和 y 定义来解决问题: volatile int x, y; int r; void f() { x =...这里我们了解一 CPU 乱序执行行为。在乱序执行时,一个处理器真正执行指令顺序由可用输入数据决定,而非程序员编写顺序。...现在思考一乱序处理器处理指令过程,我们能得到几个结论: 对于单个 CPU 指令获取是有序(通过队列实现) 对于单个 CPU 指令执行结果也是有序返回寄存器堆(通过队列实现) 由此可知,在单 CPU

1.1K30

CAS操作在ARM和x86不同实现

intel P6以及最新系列处理器保证了以下操作是原子:1.读写一个字节。2.读写16位字。3.读写32位双字。4.读写64位四字。...所以英特尔对于一些指令提供了LOCK前缀来保证这个指令原子性。Intel 64和IA-32处理器提供LOCK#信号,该信号在某些关键存储器操作期间自动置位,以锁定系统总线或等效链路。...为了更清楚理解cmxchg,需要同时看ARM和x86两种架构实现一个RISC,一个CISC,linux内核提供了两种架构实现。...linux内核原子变量定义如下: //原子变量 typedef struct { volatile int counter; //volatile禁止编译器把变量缓冲到寄存器 } atomic_t;...例如cpu0将地址m标记为独占,在strex执行前,线程被调出了,cpu1调用ldrex会清除cpu0独占,而将自己标记为独占,然后执行strxr,然后cpu0线程重新被调度,此时执行strex会失败

97930

volatile

volatile关键字字节码原语 1、volatile使用场景: DCL单例模式对象创建过程(申请内存空间,初始化对象,引用指向对象内存空间地址这三个操作不是原子操作,会发生指令重排,所以加上volatile...happens-before原则:也是jvm一个约定,简单理解就是jvm规定八种情况都要加上内存屏障 https://blog.csdn.net/hxm_Code/article/details...(参考https://zhuanlan.zhihu.com/p/133851347) 下面这段话摘自《深入理解Java虚拟机》:  “观察加入volatile关键字和没有加入volatile关键字时所生成汇编代码发现...因为CPU和其他部件进行通信都是通过总线来进行,如果总线加LOCK#锁的话,也就是说阻塞了其他CPU其他部件访问(如内存),从而使得只能有一个CPU能使用这个变量内存。...不过这里有一点需要注意:在32位平台64位数据读取和赋值是需要通过两个操作来完成,不能保证其原子性。但是好像在最新JDK中,JVM已经保证64位数据读取和赋值也是原子性操作了。

55100

C# 温故而知新: 线程篇(三)上

方法和Volatile关键字作用 Volatile关键字作用 介绍Interlocked 介绍Lock关键字 详解ReaderWriterLock 类 本章总结 参考文献 1.线程同步中一些重要概念...那就引出了下面的一个模式 1.3基元内核模式 该模式和用户模式不同,它是windows系统自身提供,使用了操作系统中内核函数,所以它能够阻塞线程提高了cpu利 用率,同时也带来了一个很可怕bug,...,但是阻止同步提高了cpu时间利用率 2.详解Thread类中VolatileRead和VolatileWrite方法和Volatile关键字 前文中,我们已经原子操作和非阻止同步概念已经有了大概认识...当然由于使用上述两个方法在复杂项目中很容易 出错,往往这种错误是很难被发现,所以微软为了让我们更好使用,便开发出了一个新关键字VolatileVolatile关键字作用 Volatile关键字本质含义是告诉编译器...作为原子性操作,Volatile关键字具有原子特性,所以线程间无法其占有,它值永远是最新

62360

Linux内核各种锁:信号量互斥锁读写锁原子锁自旋锁内存屏障等

单核的话,只有发生中断会使任务被抢占,那么可以进入临界区之前先关中断,但是多核CPU光关中断就不够了,因为当前CPU关了中断只能使得当前CPU不会运行其它要进入临界区程序,但其它CPU还是可能执行进入临界区程序...r; void f() { x = r; __asm__ __volatile__("" ::: "memory"); y = 1; } 或者将涉及到相关变量x和y用volatile关键字修饰...: volatile int x, y; 注意,C++里volatile关键字只能避免编译期指令重排,对于多CPU指令重排不起作用,所以实际上代码真正运行时候,可能又是乱序。...而Javavolatile关键字好像具有编译器、CPU两个层面的内存屏障作用。 多CPU乱序访问内存: 在单 CPU 上,不考虑编译器优化导致乱序前提下,多线程执行不存在内存乱序访问问题。...内存屏障(CPU级别)就是内存模型一部分,用于确保特定内存操作顺序,X86-64仅支持一种指令重排:Store-Load ,即读操作可能会重排到写操作前面。

34810

《CLR via C#》笔记:第5部分 线程处理(3)(完结)

volatile关键字,它可应用于以下任何类型静态或实例字段: Boolean,(S)Byte,(U)Int16,(U)Int32,(U)IntPtr,Single和 Char。...还可将volatile关键字应用于引用类型字段,以及基础类型为(S)Byte,(U)Int16或(U)Int32任何枚举字段。...JIT编译器确保易变字段所有访问都是以易变读取或写入方式执行,不必显式调用Volatile 静态Read或 Write方法。...另外,volatile关键字告诉C#和JIT编译器不将字段缓存到CPU寄存器中,确保字段所有读写操作都在RAM中进行。...(P687) 内核模式构造优点: 1、内核模式构造检测到在一个资源上竞争时,Windows会阻塞输掉线程,使它不占着一个CPU“自旋”(spinning),无谓地浪费处理器资源。

23720

Java volatile 关键字解释 用法原理 并发编程特性

再讲到volatile关键字之前我们需要了解一内存模型相关概念以及并发编程中三个特性:原子性,可见性和有序性。...2. volatile关键字 一旦一个共享变量(类成员变量、类静态成员变量)被volatile修饰之后,那么就具备了两层语义: 保证了不同线程这个变量进行操作时可见性,即一个线程修改了某个变量值...2.1 volatile保证原子性吗? 我们知道volatile关键字保证了操作可见性,但是volatile能保证变量操作是原子性吗?...写入动作也会引起别的CPU或者别的内核无效化其Cache,相当于让新写入别的线程可见。 3....正确使用volatile关键字 synchronized关键字是防止多个线程同时执行一段代码,那么就会很影响程序执行效率,而volatile关键字在某些情况性能要优于synchronized,但是要注意

38231

JVM技术总结之七——volatile关键字

接上篇《JVM技术总结之六——JVM锁优化》 七. volatile 关键字 参考地址:《并发关键字volatile(重排序和内存屏障)》 7.1 volatile 关键字 Volatile 变量具有...它有两条特性: 禁止指令重排序;保证了有序性; 当一个线程修改了内存,volatile 关键字保证它能够立即刷新到主内存中;这条特性保证了 volatile 关键字可见性; 7.2 指令重排序 通常情况...Store Barrier,可以将写入缓存中最新数据更新写入到主内存中,令其他线程可见; volatile 读前插读屏障,写后加写屏障,避免 CPU 重排导致问题,实现多线程之间数据可见性。...在 L 与后续读操作之前,保证 S 要写入数据写入完毕; 该操作保证了 S 操作写入所有处理器可见,开销最大; volatile 读操作与写操作,在前后分别插入了内存屏障: volatile...如果 synchronized 使用次数过多,就意味着模态切换次数太多,消耗内核资源过多。 锁优化(自旋锁、锁释放、锁粗化、轻量级锁、偏向锁)是针对 synchronized 关键字进行优化;

51530

Java 开发, volatile 你必须了解一

所以说在多线程环境中,需要保证这两个特性功能,可以使用 volatile 关键字volatile 是如何保证可见性 说到可见性,就要了解一计算机处理器和主存了。...因为 volatile 保证内存可见性,其实是用到了 CPU 保证缓存一致性 MESI 协议。MESI 协议内容较多,这里就不做说明,请各位同学自己去查询一吧。...总之用了 volatile 关键字,当某线程 volatile 变量修改会立即回写到主存中,并且导致其他线程缓存行失效,强制其他线程再使用变量时,需要从主存中读取。...而使用 volatile 关键字,也就是使用了 “一个 volatile修饰变量写,happens-before于任意后续该变量读” 这一原则,对应到上面的初始化过程,步骤2 和 3 都是...最后 通过 volatile 关键字,我们了解了一并发编程中可见性和有序性,当然只是简单了解。更深入了解,还得靠各位同学自己去钻研。如果感觉还是有点作用的话,欢迎点个推荐。

79420

Linux内核理解 Memory barrier(内存屏障)

本文例子均在 Linux(g++)验证通过,CPU 为 X86-64 处理器架构。所有罗列 Linux 内核代码也均在(或只在)X86-64 下有效。...编译时内存乱序访问在编译时,编译器代码做出优化时可能改变实际执行指令顺序(例如 gcc O2 或 O3 都会改变实际执行指令顺序):// test.cppint x, y, r;void f(...本例中,我们还可以使用 volatile 这个关键字来避免编译时内存乱序访问(而无法避免后面要说运行时内存乱序访问)。...volatile 关键字能够让相关变量之间在内存访问上避免乱序,这里可以修改 x 和 y 定义来解决问题:volatile int x, y;int r;void f(){ x = r;...y = 1;}现加上了 volatile 关键字,这使得 x 相对于 y、y 相对于 x 在内存访问上有序。

1.8K00

The Myth of volatileJDK1.5之前volatileJDK1.5之后volatilevolatile足够了吗?volatile VS 锁结论

但我觉得用来形容volatile关键字却再合适不过了。volatile字面意思是“易变,反复无常”,但它实际意思却复杂得多。大量初学者面对着它无比渴求,希望一窥究竟,却很难在实际项目中用。...JDK1.5之前volatile JDK1.5之前,volatile还是比较好理解,即volatile是设计被用来简单解决变量可见性。听上去很玄乎?容我来说明一。 ?...多核CPU访问内存模型 上图是一个一般CPU和内存体系结构简化示意图。程序运行时,每个线程会被调度到某一个CPU内核上。为了提高性能,CPU内核都有自己缓存。...多核CPU对内存修改不直接对外可见 这个问题被简称为变量可见性问题。volatile关键字用来解决这个问题。...似乎一个关键字在满足了一个复杂条件,达成一个很反人类常识结果。这超出了本文范围,也许可以找个时间专门探究一

1.6K100

万字长文说透 volatile 原理和面试知识点!

1、volatile 关键字在 Java 中有什么作用? volatile 是一个特殊修饰符,只有成员变量才能使用它。...在 Java 并发程序缺少同步类情况,多线程对成员变量操作对其它线程是透明volatile 变量可以保证下一个读取操作会在前一个写操作之后发生。...2、面试官: 继续,说说你 volatile 关键字理解。...如果把加入 volatile 关键字代码和未加入 volatile 关键字代码都生成汇编代码,会发现加入 volatile 关键字代码会多出一个 lock 前缀指令。...lock 前缀指令实际相当于一个内存屏障,内存屏障提供了以下功能: 重排序时不能把后面的指令重排序到内存屏障之前位置 使得本 CPU Cache 写入内存 写入动作也会引起别的 CPU 或者别的内核无效化其

78210

C# Volatile

1.Overview 经常研究.NET源码库小伙伴会经常看到一个关键字volatile,那它在开发当中作用是什么呢?...我们一起来看看官方文档里是怎么描述,如下: “volatile 关键字指示一个字段可以由多个同时执行线程修改。出于性能原因,编译器,运行时系统甚至硬件都可能重新排列存储器位置读取和写入。...这个时候就需要用volatile关键字告诉编译器不需要这样优化,表示用volatile定义变量会被改变,每次都必须从内存中读取,而不能把他放在CPU cache或寄存器中重复使用。...其他类型(包括 double 和 long)无法标记为 volatile,因为这些类型字段读取和写入不能保证是原子。...若要保护这些类型字段多线程访问,请使用 Interlocked 类成员或使用 lock 语句保护访问权限。 volatile 关键字只能应用于 class 或 struct 字段。

38020
领券