`

java并发特性,原子性、有序性、可见性

 
阅读更多
  1. 原子性是指一个操作是不可中断的。即使是在多个线程一起执行的时候,一个操作一旦开始,就不会被其它线程干扰。

    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地址,则会有如下运行结果:
    1111111111111111111111111111111111111111111111111111111111111111
    0000000000000000000000000000000000000000000000000000000000000000
    0000000000000000000000000000000011111111111111111111111111111111 
    //很明显test的值被破坏了
    4294967295

     

  2. 有序性

    有序性即程序执行的顺序按照代码的先后顺序执行。
          在Java内存模型中,允许编译器和处理器对指令进行重排序,但是重排序过程不会影响到单线程程序的执行,却会影响到多线程并发执行的正确性。(例如:重排的时候某些赋值会被提前)
    在Java里面,可以通过volatile关键字来保证一定的“有序性”(具体原理在下一节讲述)。另外可以通过synchronized和Lock来保证有序性,很显然,synchronized和Lock保证每个时刻是有一个线程执行同步代码,相当于是让线程顺序执行同步代码,自然就保证了有序性

     

  3. 可见性 

     可见性是指当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。

    可见性,Java提供了volatile关键字来保证可见性。
    当一个共享变量被volatile修饰时,它会保证修改的值会立即被更新到主存,当有其他线程需要读取时,它会去内存中读取新值。
    而普通的共享变量不能保证可见性,因为普通共享变量被修改之后,什么时候被写入主存是不确定的,当其他线程去读取时,此时内存中可能还是原来的旧值,因此无法保证可见性。
    另外,通过synchronized和Lock也能够保证可见性,synchronized和Lock能保证同一时刻只有一个线程获取锁然后执行同步代码,并且在释放锁之前会将对变量的修改刷新到主存当中。因此可以保证可见性。

 

分享到:
评论

相关推荐

    14、深入理解并发可见性、有序性、原子性与JMM内存模型

    深入理解并发可见性、有序性、原子性与JMM内存模型深入理解并发可见性、有序性、原子性与JMM内存模型深入理解并发可见性、有序性、原子性与JMM内存模型深入理解并发可见性、有序性、原子性与JMM内存模型深入理解并发...

    java并发理论基础、可见性、原子性、有序性详解

    Java并发编程是提升系统效率的关键技术...总之,理解Java并发编程中的可见性、原子性和有序性是编写高效、安全并发程序的关键。开发者需要掌握如何利用并发提升性能,同时处理好潜在的问题,确保程序的正确性和稳定性。

    并发二:原子性、可见性、有序性.pdf

    本文主要讲解了Java内存模型(JMM)中关于并发编程的三个基本概念:原子性、可见性和有序性。 原子性 原子性是指一个操作不会被线程调度机制打断,一旦开始,就一直运行到结束,中间不会有任何线程切换(context ...

    14、深入理解并发可见性、有序性、原子性与JMM内存模型(1).pdf

    根据提供的文档信息,本文将详细解析并发编程中的关键概念——原子性、可见性及有序性,并结合Java内存模型(JMM)来深入理解这些概念。同时,我们也会通过具体示例来探讨这些问题在实际编程中的应用。 ### 一、并发...

    Java多线程中提到的原子性和可见性、有序性1

    Java多线程编程中,原子性、可见...总结来说,原子性、可见性和有序性是Java多线程编程中保证并发安全的重要概念。通过合理使用Java提供的并发工具和关键字,开发者可以有效地管理线程之间的交互,确保程序的正确运行。

    Java内存模型--原子性;有序性;可见性1

    总结来说,Java内存模型通过原子性、有序性和可见性保证了多线程环境下的数据一致性。理解并熟练运用这些概念是编写高效、线程安全的Java代码的基础。在实际开发中,应根据需求选择合适的方式来确保这三个特性,以...

    《java 并发编程实战高清PDF版》

    书中详细阐述了可见性、原子性和有序性这些概念,并通过`volatile`关键字和`final`修饰符的使用来演示它们的作用。 除了锁,Java还提供了其他同步机制,如`java.util.concurrent`包下的并发工具类。其中包括`...

    java并发编程内部分享PPT

    volatile确保变量的可见性和有序性,但不保证原子性。Lock接口提供了更细粒度的锁控制,可以实现公平锁、非公平锁、可重入锁等。Atomic类提供了原子操作,适用于简单的共享变量更新场景。 Java内存模型(JMM)是...

    ( Java并发程序设计教程.zip )高清版 PDF

    JMM规定了线程如何访问共享内存,如何保证可见性、原子性和有序性。书中会详细阐述 volatile 的工作原理,以及如何利用其确保线程间的正确通信。 此外,Java并发集合框架是另一个重要章节。它包含一系列优化过的...

    Java并发编程实践.pdf

    - **volatile关键字**:用于修饰变量,确保变量的可见性和有序性,但不保证原子性操作。 - **Lock接口及其实现类**:提供比synchronized更高级别的锁机制,如ReentrantLock等。 #### 三、Java并发工具类 ##### 3.1...

    java并发编程

    8. **volatile 关键字**: 它确保了变量的可见性和有序性,但不保证原子性。当多个线程访问同一变量时,volatile能保证每个线程都能看到最新的值。 9. **synchronized 关键字**: 它用于保证同一时间只有一个线程可以...

    2023 java并发编程手册

    JMM 包括变量的可见性、原子性和有序性等概念。 2. 并发编程基础 并发编程是指在单个处理器或多个处理器上执行多个线程的技术。Java 语言提供了多种并发编程机制,包括线程、Runnable、Callable、Executor、Fork/...

    java并发编程实战高清版pdf

    9. **Java内存模型(JMM)**:理解JMM对于理解并发编程中的可见性、有序性和一致性至关重要。它规定了线程如何访问共享内存,并定义了 volatile、synchronized 和 final 关键字的作用。 10. **并发性能分析与调优**...

    java并发编程实战.zip

    3. **volatile与可见性**:详细解析volatile关键字的作用,它是如何确保多线程环境下的变量可见性和有序性,以及与普通变量的区别。 4. **锁与并发工具类**:介绍了Java.util.concurrent包中的锁机制,如...

    JAVA并发编程实践高清版带书签PDF

    3. **Java内存模型(JMM)**:详细解析了Java内存模型的工作原理,包括可见性、有序性和原子性,这些是理解和使用并发的关键。 4. **锁与同步替代方案**:除了synchronized,书中还介绍了Lock接口及其实现,如...

    Java并发编程全景图.pdf

    volatile关键字保证了变量的可见性和部分有序性。synchronized关键字提供了互斥访问,可以用于方法或代码块,确保一次只有一个线程可以执行特定的代码。CAS(Compare-And-Swap)是一种无锁的同步机制,用于实现非...

    java 并发编程实践

    - JMM规定了线程如何访问和修改内存,以及如何确保内存可见性和有序性,理解JMM对于编写高效的并发代码至关重要。 8. **Java 5及以后的并发改进** - **`java.util.concurrent`包的引入**:提供了高效并发工具,如...

    JAVA并发编程实践 中文 高清 带书签 完整版 Doug Lea .pdf

    - **volatile变量**:用于确保变量的可见性和一定程度上的有序性。 #### 3.3 原子操作与原子类 - **原子操作**:在单个处理器上执行时不会被中断的操作。 - **AtomicInteger、AtomicLong等**:提供了原子操作的封装...

    JAVA并发编程实践 pdf

    接着,书中会深入讨论Java内存模型(JMM)和volatile关键字,这两个概念对于理解和解决并发编程中的可见性、有序性和原子性问题至关重要。同时,书中还会涵盖synchronized关键字的用法,包括可重入锁、同步块和同步...

    Java并发编程的艺术

    本章详细介绍了内存可见性、原子性和有序性等概念,并探讨了它们如何影响程序的行为。作者们还讨论了volatile关键字的作用机制以及它如何确保内存可见性的。通过这些深入的分析,读者能够更加清晰地理解Java内存模型...

Global site tag (gtag.js) - Google Analytics