Java并发之原子性 有序性 可见性及Happen Before原则

Java并发之原子性、有序性、可见性及Happen Before原则

原子性

Java中的原子性是指一个操作或者多个操作,要么全部都执行并且执行的过程不会被任何因素中断,要么就全部都不执行。在Java中,原子性可以通过synchronizedLock关键字实现。除此之外,Java实现了java.util.concurrent.atomic包,提供了一系列原子性操作类,比如AtomicIntegerAtomicLong等等。这些原子性类中,常用的方法有:compareAndSetincrementAndGetdecrementAndGet等等。

有序性

Java中的有序性是指程序执行时,可能会对指令进行重排序,但是最终结果不变。在Java中,要保证有序性,可以使用volatile关键字,或者是synchronizedLock关键字。在使用volatile时,会保证读写操作的原子性和有序性。此外,Java中还有一种特别的有序性,称为程序顺序原则(POO,Program Order Rule),POO指的是在一个线程中,程序顺序规则保证了代码按照写在代码中的顺序依次执行。

可见性

Java中的可见性是指当一个线程修改了某个共享变量的值时,其他线程是否能够立即知道这个变量被修改的事实。在Java中,要保证可见性,可以使用volatile关键字,或者是synchronizedLock关键字。使用volatile关键字时,会强制线程每次都从主内存中读取变量的值,而不是从线程的本地缓存中读取。此外,Java中还有一种实现可见性的方法,就是使用synchronizedLock关键字。

Happen Before原则

Java中的Happen Before原则是指,在一定的情况下,任何一个操作事件的执行结果都能被后续的操作事件所看到。Java中有一些规则,可以确保满足Happen Before原则,包括:

  • 程序顺序原则(POO)
  • 传递性
  • volatile变量规则
  • 锁规则
  • 线程启动规则
  • 线程中断规则
  • 线程终结规则

其中,传递性规则表示:如果操作A Happen Before操作B,操作B Happen Before操作C,那么操作A Happen Before操作C。

示例说明

示例一

public class Example1 {
    private int count = 0;

    public synchronized void increase() {
        count++;
    }

    public static void main(String[] args) throws InterruptedException {
        final Example1 example = new Example1();
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                for (int j = 0; j < 1000; j++) {
                    example.increase();
                }
            }).start();
        }

        Thread.sleep(5000);
        System.out.println(example.count);
    }
}

上述代码创建了一个Example1类,该类中有一个成员变量count,和一个同步方法increase。通过创建10个线程,让它们同时访问increase方法,每次访问后将count自增1。由于synchronized关键字的保证,该程序将可以保证原子性和可见性。最终执行结果应该是:10000

示例二

public class Example2 {

    private volatile int value = 0;

    public void setValue(int value) {
        this.value = value;
    }

    public int getValue() {
        return value;
    }

    public static void main(String[] args) throws InterruptedException {
        final Example2 example = new Example2();
        new Thread(() -> {
            try {
                Thread.sleep(1000);
                example.setValue(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();

        while (example.getValue() == 0) {
            Thread.sleep(100);
        }

        System.out.println("value: " + example.getValue());
    }
}

上述代码创建了一个Example2类,其中有一个成员变量value,并且使用了volatile关键字进行修饰。在主线程中,创建了一个线程,并且在该线程中1秒后将value设置为1。在主线程中,通过while循环判断value是否为0。由于volatile关键字的保证,可以保证在判断value时,已经能获取到最新的value值,因此该程序将可以保证可见性。最终执行结果应该是:value: 1

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java并发之原子性 有序性 可见性及Happen Before原则 - Python技术站

(0)
上一篇 2023年5月17日
下一篇 2023年5月17日

相关文章

  • Spring-Boot中如何使用多线程处理任务方法

    关于Spring Boot中如何使用多线程处理任务,有以下几种方法: 方式一:使用Java中的Thread或Executor 可以使用Java中的Thread或Executor进行多线程处理任务,具体操作步骤如下: 在Spring Boot应用主类中创建ExecutorService: @Bean public ExecutorService executo…

    多线程 2023年5月16日
    00
  • Java多线程之死锁的出现和解决方法

    Java多线程之死锁的出现和解决方法 死锁的概念 死锁是指在多线程并发的情况下,两个或更多线程在互相等待对方持有的资源,造成程序的无限等待。这种情况下,程序将永远不能终止,只能通过强制终止才能解决。因此,死锁是一种常见的并发编程问题,需要引起我们的重视。 在出现死锁时,我们常用的解决办法是打破死锁的循环依赖关系,从而解除死锁的状态。下面,我们将介绍一些解决死…

    多线程 2023年5月17日
    00
  • PHP读写文件高并发处理操作实例详解

    下面我详细讲解一下“PHP读写文件高并发处理操作实例详解”。 1. 需求分析 在高并发的情况下,PHP读写文件操作可能会出现问题,比如同时有多个请求来读取/写入同一个文件,可能会出现文件被多次读写的情况,导致数据混乱。因此,我们需要对PHP读写文件进行高并发的处理,保证数据的正确性。 2. 解决方案 针对以上问题,我们可以采用加锁的方式来解决。具体的实现方式…

    多线程 2023年5月16日
    00
  • Java线程并发工具类CountDownLatch原理及用法

    Java线程并发工具类CountDownLatch原理及用法 简介 CountDownLatch是一种非常实用的java线程同步工具类,主要作用是允许一个或多个线程一直等待,在其他线程执行完一组操作之后才执行。 CountDownLatch主要有两个方法:* countDown() : 对计数器进行操作,将计数器的值减少1* await() : 调用该方法的…

    多线程 2023年5月16日
    00
  • java并发编程之cas详解

    Java并发编程之CAS详解 一、CAS的概述 CAS(Compare And Swap),中文名是比较并交换,是一种多线程并发机制,用于实现无锁算法。它包含三个操作数——内存位置(V)、预期原值(A)和新值(B)。如果内存位置的值与预期原值相匹配,那么处理器会自动将该位置值更新成新值。否则,处理器不做任何操作。在任何情况下,都会返回该位置原有的值。CAS是…

    多线程 2023年5月17日
    00
  • C# List 并发丢数据问题原因及解决方案

    C# List 并发丢数据问题原因及解决方案 问题描述 在多线程环境下,使用C#的List时,会存在添加元素丢失、重复、越界等问题,导致程序出现异常或不可预料的结果。这是由于List本身并不是线程安全的集合类,多个线程同时对其进行写操作时,会导致竞争条件,从而出现数据异常。 原因分析 List是一个基于数组的集合类型,当多个线程同时对其进行写操作时,可能会导…

    多线程 2023年5月17日
    00
  • Java httpClient连接池支持多线程高并发的实现

    Java httpClient是一种开源的基于Http的请求和响应类型,它可以通过连接池技术适用于高并发的请求场景,下面是httpClient连接池支持多线程高并发的实现攻略: 1. 引入依赖 <dependency> <groupId>org.apache.httpcomponents</groupId> <art…

    多线程 2023年5月16日
    00
  • Java线程同步方法实例总结

    Java线程同步方法实例总结 什么是线程同步? 在Java多线程中,多个线程同时访问同一份数据时,就有可能出现数据的不一致性。而线程同步就是一种提供独占访问共享资源的机制,确保同时只有一个线程访问共享资源,从而避免并发访问导致的数据不一致性问题。 如何实现线程同步? Java语言提供了两种实现线程同步的机制:synchronized同步块和Lock锁。 sy…

    多线程 2023年5月16日
    00
合作推广
合作推广
分享本页
返回顶部