Java多线程并发编程 并发三大要素

Java多线程并发编程:并发三大要素

多线程编程本质上就是并发编程,而对于并发编程,有三个重要的要素:原子性、可见性和有序性。

原子性

原子性指的是一个操作是不可被打断的,即要么执行成功,要么执行失败,不会存在执行一半的情况。在多线程环境下,多个线程同时访问同一个变量时,可能会发生数据竞争。数据竞争常常发生在复合操作时,例如i++这样的简单操作,看似只有一行代码,但是其中包含了读取i的值、计算i+1、将i+1的值写入内存、刷新缓存等多个操作,这些操作不是原子性的,因此可能会出现数据竞争。为了解决数据竞争,Java提供了synchronized和lock关键字来保证线程安全。

下面是一个简单的数据竞争示例,未加锁对共享资源进行修改:

public class Counter extends Thread{
    private static int count = 0;

    public static void main(String[] args) throws InterruptedException {
        Counter c1 = new Counter();
        Counter c2 = new Counter();

        c1.start();
        c2.start();

        c1.join();
        c2.join();

        System.out.println("count = " + count);
    }

    public void run() {
        for(int i=0; i<10000; i++) {
            count++;
        }
    }
}

在多次运行后会发现结果并不稳定,产生了数据竞争。如果对count++加锁,可以解决数据竞争的问题。

可见性

可见性指的是多个线程访问同一个变量时,变量在内存中的值应该保持一致。但是,由于JVM为了提高执行效率,会对变量进行优化,在执行过程中将变量缓存在CPU的寄存器或者CPU Cache中;此时,其他线程可能无法立即看到该变量的变化。这就导致线程之间对同一个变量的值是不一致的。为了解决可见性问题,Java提供了volitile关键字来保证共享变量的修改对线程的可见性。

下面是一个可见性问题的示例:

public class VisibilityDemo extends Thread {

    private boolean stop = false;

    public void stopMe() {
        stop = true;
    }

    public void run() {
        int i = 0;
        while (!stop) {
            i++;
        }
        System.out.println("Thread stoped." + i);
    }

    public static void main(String[] args) throws InterruptedException {
        VisibilityDemo thread = new VisibilityDemo();
        thread.start();
        Thread.sleep(1000);
        thread.stopMe();
        System.out.println("stop flag stoped.");
    }
}

该程序会启动一个线程,并且标志位stop的初始值为false。在主线程中,让线程睡眠1000ms后,将stop标志位设置为true,但由于可见性问题,线程并未停止。如果将stop标志位加上volatile修饰符,可避免可见性问题。

有序性

有序性指的是在多线程执行时,指令不能乱序执行,必须按照代码的原有顺序执行。在Java内存模型中,有一些指令是具有同步性质的,例如synchronized、volatile和Lock等关键字。在这些指令的前后,会自动加入内存屏障,保证指令按照代码原有顺序执行。在Java中,可以使用synchronized关键字或者volatile关键字保证内存屏障的插入。

示例代码:

import java.util.concurrent.atomic.AtomicInteger;

public class OrderDemo extends Thread {

    static AtomicInteger x = new AtomicInteger(0);
    static AtomicInteger y = new AtomicInteger(0);
    static AtomicInteger a = new AtomicInteger(0);
    static AtomicInteger b = new AtomicInteger(0);

    public void run() {
        int i = a.get();
        x.set(i);
        b.set(1);
    }

    public static void main(String[] args) throws InterruptedException {
        Thread one = new Thread(new Runnable() {
            public void run() {
                a.set(1);
                y.set(b.get());
            }
        });

        Thread other = new OrderDemo();
        one.start();
        other.start();
        one.join();
        other.join();
        System.out.println("(" + x.get() + "," + y.get() + ")");
    }
}

该代码中,one线程中,先将a的值设置为1,再将b的值设置为1。在other线程中,a的值被获取赋值给i,再将i的值给x,最后将1赋值给b,程序输出结果会出现不同的情况,有可能输出(0,1),有时候输出(0,0)。加上synchronized关键字或者volatile关键字后,可以避免乱序执行问题,使输出值恒定为(1,1)。

以上就是Java多线程并发编程中的三大要素:原子性、可见性和有序性的详细讲解以及示例分析。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java多线程并发编程 并发三大要素 - Python技术站

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

相关文章

  • Android版多线程下载 仿下载助手(最新)

    下面是《Android版多线程下载 仿下载助手(最新)》的完整攻略。 一、项目说明 本项目为 Android 版本多线程下载,实现了仿照下载助手的功能,支持多线程下载、暂停和继续下载、断点续传、下载速度统计等等。 二、环境配置 首先,我们需要安装以下环境: JDK Android Studio Git 三、下载源码 我们可以在 GitHub 上将项目克隆到本…

    多线程 2023年5月16日
    00
  • C# 异步多线程入门到精通之ThreadPool篇

    C# 异步多线程入门到精通之ThreadPool篇攻略 在C#程序中,如果需要同时执行多个任务,则要使用多线程技术。但是在使用多线程时,我们需要注意资源竞争和死锁的问题。如果不处理好这些问题,程序可能会出现异常错误。 C#提供了ThreadPool类,可以简化多线程的编程。ThreadPool类可以在应用程序中创建一个线程池,然后将多个任务加入到线程池中,线…

    多线程 2023年5月17日
    00
  • Java多线程事务管理的实现

    Java多线程事务管理的实现是一项重要的任务,它可以帮助开发者更加方便地进行事务管理。在下面的攻略中,我将详细讲解实现Java多线程事务管理的过程及其示例。 实现Java多线程事务管理的过程 实现Java多线程事务管理的过程大体可以分为以下几个步骤: 定义事务管理器类。 定义事务类并继承Thread类。 重写run()方法。 定义回滚方法。 定义提交方法。 …

    多线程 2023年5月17日
    00
  • JDK源码之线程并发协调神器CountDownLatch和CyclicBarrier详解

    JDK源码之线程并发协调神器CountDownLatch和CyclicBarrier详解 在Java并发编程中,经常需要进行线程间的协调,以达到控制线程执行顺序、提高程序运行效率等目的。CountDownLatch和CyclicBarrier是Java中最常用的线程协调工具,本文将详细介绍这两个工具的用法和源码实现细节。 CountDownLatch Cou…

    多线程 2023年5月16日
    00
  • 深入理解Python 多线程

    深入理解Python 多线程:完整攻略 前言 随着互联网时代的到来,Python成为一款备受欢迎的编程语言。然而,在Python中,多线程技术十分重要。在许多涉及到I/O密集型操作的场景中,多线程的技术可以对性能提升有很大的帮助。在本篇文章中,我们将探讨如何深入理解Python多线程的工作原理。 Python多线程简介 在Python中,我们可以使用内置的’…

    多线程 2023年5月17日
    00
  • Java创建多线程异步执行实现代码解析

    Java创建多线程异步执行是很常见的开发需求,在实际开发过程中也经常用到,本篇文章将细致地讲解如何实现这一功能,包括创建多线程的方式、线程的基础操作、如何使用Java的Concurrent包以及线程安全的问题等问题。 1. 创建多线程 Java中创建多线程的方式有很多,这里主要介绍两种方式。 1.1 继承Thread类 第一种方式就是继承Thread类,并重…

    多线程 2023年5月17日
    00
  • Python 微信爬虫完整实例【单线程与多线程】

    Python 微信爬虫完整实例【单线程与多线程】攻略 本文介绍了如何用Python实现微信公众号文章的爬取,并提供了单线程与多线程两种实现方式,以便读者可以根据自己的需求选择适用的方法。 准备工作 在开始爬虫之前,需准备如下软件工具: Python 3.x Chrome浏览器 Chromedriver requests bs4 lxml selenium 单…

    多线程 2023年5月16日
    00
  • .NET并发编程之函数闭包

    .NET并发编程是一个非常广泛的话题,其中函数闭包是一个非常重要的部分。在本篇攻略中,我将详细讲解什么是函数闭包,它的用途以及如何在.NET环境中使用它来实现并发编程。 什么是函数闭包 先从概念上来讲,函数闭包是一种特殊的函数,它可以访问其外部环境中的变量和函数,即使这些变量和函数已经不再存在,也可以继续使用。它通常用来创建函数工厂,或者是实现某些高级编程模…

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