-
原子性是指一个操作是不可中断的。即使是在多个线程一起执行的时候,一个操作一旦开始,就不会被其它线程干扰。
Java中的原子操作包括:
1)除long和double之外的基本类型的赋值操作
2)所有引用reference的赋值操作3)java.concurrent.Atomic.* 包中所有类的一切操作。但是java对long和double的赋值操作是非原子操作!!long和double占用的字节数都是8,也就是64bits。在32位操作系统上对64位的数据的读写要分两步完成,每一步取32位数据。这样对double和long的赋值操作就会有问题:如果有两个线程同时写一个变量内存,一个进程写低32位,而另一个写高32位,这样将导致获取的64位数据是失效的数据。因此需要使用volatile关键字来防止此类现象。volatile本身不保证获取和设置操作的原子性,仅仅保持修改的可见性。但是java的内存模型保证声明为volatile的long和double变量的get和set操作是原子的。public class UnatomicLong implements Runnable { private static long test = 0; private final long val; public UnatomicLong(long val) { this.val = val; } @Override public void run() { while (!Thread.interrupted()) { test = val; //两个线程都试图将自己的私有变量val赋值给类私有静态变量test } } public static void main(String[] args) { Thread t1 = new Thread(new UnatomicLong(-1)); Thread t2 = new Thread(new UnatomicLong(0)); System.out.println(Long.toBinaryString(-1)); System.out.println(pad(Long.toBinaryString(0), 64)); t1.start(); t2.start(); long val; while ((val = test) == -1 || val == 0) { //如果静态成员test的值是-1或0,说明两个线程操作没有交叉 } System.out.println(pad(Long.toBinaryString(val), 64)); System.out.println(val); t1.interrupt(); t2.interrupt(); } // prepend 0s to the string to make it the target length private static String pad(String s, int targetLength) { int n = targetLength - s.length(); for (int x = 0; x < n; x++) { s = "0" + s; } return s; } }
运行发现程序在while循环时进入了死循环,这是因为使用的JVM是64bits。在64位JVM中double和long的赋值操作是原子操作。在eclipse中修改jre为一个32bit的JVM地址,则会有如下运行结果:111111111111111111111111111111111111111111111111111111111111111100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011111111111111111111111111111111//很明显test的值被破坏了4294967295 -
有序性
有序性即程序执行的顺序按照代码的先后顺序执行。
在Java内存模型中,允许编译器和处理器对指令进行重排序,但是重排序过程不会影响到单线程程序的执行,却会影响到多线程并发执行的正确性。(例如:重排的时候某些赋值会被提前)
在Java里面,可以通过volatile关键字来保证一定的“有序性”(具体原理在下一节讲述)。另外可以通过synchronized和Lock来保证有序性,很显然,synchronized和Lock保证每个时刻是有一个线程执行同步代码,相当于是让线程顺序执行同步代码,自然就保证了有序性 -
可见性
可见性是指当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。
可见性,Java提供了volatile关键字来保证可见性。
当一个共享变量被volatile修饰时,它会保证修改的值会立即被更新到主存,当有其他线程需要读取时,它会去内存中读取新值。
而普通的共享变量不能保证可见性,因为普通共享变量被修改之后,什么时候被写入主存是不确定的,当其他线程去读取时,此时内存中可能还是原来的旧值,因此无法保证可见性。
另外,通过synchronized和Lock也能够保证可见性,synchronized和Lock能保证同一时刻只有一个线程获取锁然后执行同步代码,并且在释放锁之前会将对变量的修改刷新到主存当中。因此可以保证可见性。
相关推荐
深入理解并发可见性、有序性、原子性与JMM内存模型深入理解并发可见性、有序性、原子性与JMM内存模型深入理解并发可见性、有序性、原子性与JMM内存模型深入理解并发可见性、有序性、原子性与JMM内存模型深入理解并发...
Java并发编程是提升系统效率的关键技术...总之,理解Java并发编程中的可见性、原子性和有序性是编写高效、安全并发程序的关键。开发者需要掌握如何利用并发提升性能,同时处理好潜在的问题,确保程序的正确性和稳定性。
本文主要讲解了Java内存模型(JMM)中关于并发编程的三个基本概念:原子性、可见性和有序性。 原子性 原子性是指一个操作不会被线程调度机制打断,一旦开始,就一直运行到结束,中间不会有任何线程切换(context ...
根据提供的文档信息,本文将详细解析并发编程中的关键概念——原子性、可见性及有序性,并结合Java内存模型(JMM)来深入理解这些概念。同时,我们也会通过具体示例来探讨这些问题在实际编程中的应用。 ### 一、并发...
Java多线程编程中,原子性、可见...总结来说,原子性、可见性和有序性是Java多线程编程中保证并发安全的重要概念。通过合理使用Java提供的并发工具和关键字,开发者可以有效地管理线程之间的交互,确保程序的正确运行。
总结来说,Java内存模型通过原子性、有序性和可见性保证了多线程环境下的数据一致性。理解并熟练运用这些概念是编写高效、线程安全的Java代码的基础。在实际开发中,应根据需求选择合适的方式来确保这三个特性,以...
书中详细阐述了可见性、原子性和有序性这些概念,并通过`volatile`关键字和`final`修饰符的使用来演示它们的作用。 除了锁,Java还提供了其他同步机制,如`java.util.concurrent`包下的并发工具类。其中包括`...
volatile确保变量的可见性和有序性,但不保证原子性。Lock接口提供了更细粒度的锁控制,可以实现公平锁、非公平锁、可重入锁等。Atomic类提供了原子操作,适用于简单的共享变量更新场景。 Java内存模型(JMM)是...
JMM规定了线程如何访问共享内存,如何保证可见性、原子性和有序性。书中会详细阐述 volatile 的工作原理,以及如何利用其确保线程间的正确通信。 此外,Java并发集合框架是另一个重要章节。它包含一系列优化过的...
- **volatile关键字**:用于修饰变量,确保变量的可见性和有序性,但不保证原子性操作。 - **Lock接口及其实现类**:提供比synchronized更高级别的锁机制,如ReentrantLock等。 #### 三、Java并发工具类 ##### 3.1...
8. **volatile 关键字**: 它确保了变量的可见性和有序性,但不保证原子性。当多个线程访问同一变量时,volatile能保证每个线程都能看到最新的值。 9. **synchronized 关键字**: 它用于保证同一时间只有一个线程可以...
JMM 包括变量的可见性、原子性和有序性等概念。 2. 并发编程基础 并发编程是指在单个处理器或多个处理器上执行多个线程的技术。Java 语言提供了多种并发编程机制,包括线程、Runnable、Callable、Executor、Fork/...
9. **Java内存模型(JMM)**:理解JMM对于理解并发编程中的可见性、有序性和一致性至关重要。它规定了线程如何访问共享内存,并定义了 volatile、synchronized 和 final 关键字的作用。 10. **并发性能分析与调优**...
3. **volatile与可见性**:详细解析volatile关键字的作用,它是如何确保多线程环境下的变量可见性和有序性,以及与普通变量的区别。 4. **锁与并发工具类**:介绍了Java.util.concurrent包中的锁机制,如...
3. **Java内存模型(JMM)**:详细解析了Java内存模型的工作原理,包括可见性、有序性和原子性,这些是理解和使用并发的关键。 4. **锁与同步替代方案**:除了synchronized,书中还介绍了Lock接口及其实现,如...
volatile关键字保证了变量的可见性和部分有序性。synchronized关键字提供了互斥访问,可以用于方法或代码块,确保一次只有一个线程可以执行特定的代码。CAS(Compare-And-Swap)是一种无锁的同步机制,用于实现非...
- JMM规定了线程如何访问和修改内存,以及如何确保内存可见性和有序性,理解JMM对于编写高效的并发代码至关重要。 8. **Java 5及以后的并发改进** - **`java.util.concurrent`包的引入**:提供了高效并发工具,如...
- **volatile变量**:用于确保变量的可见性和一定程度上的有序性。 #### 3.3 原子操作与原子类 - **原子操作**:在单个处理器上执行时不会被中断的操作。 - **AtomicInteger、AtomicLong等**:提供了原子操作的封装...
接着,书中会深入讨论Java内存模型(JMM)和volatile关键字,这两个概念对于理解和解决并发编程中的可见性、有序性和原子性问题至关重要。同时,书中还会涵盖synchronized关键字的用法,包括可重入锁、同步块和同步...
本章详细介绍了内存可见性、原子性和有序性等概念,并探讨了它们如何影响程序的行为。作者们还讨论了volatile关键字的作用机制以及它如何确保内存可见性的。通过这些深入的分析,读者能够更加清晰地理解Java内存模型...