线程的原子性、可见性、有序性及线程安全知识整理

news2024/9/23 9:24:24

要想保证线程安全,必须同时满足原子性、可见性、有序性。

一、定义

1.1 原子性

一个操作或者多个操作,要么全部执行,并且执行的过程不会被打断, 要么就全部不执行(一个操作是不可被分割的)。

Java中实现线程原子性主要有两种方式:

1、互斥锁:在同一时刻只允许一个线程对共享资源进行访问和操作,而其他线程则需要等待锁的释放才能继续执行。如:synchronized和ReentrantLock等机制来实现锁的获取、释放和等待。

2、原子变量类:Java提供了一些基本类型的原子变量类(如 AtomicInteger、AtomicBoolean 等),这些变量类保证了读取和修改操作的原子性,从而避免了线程安全问题。

我们来看下几个例子:

a = 0 是原子操作 
a++ (a = a + 1) 则不是。因为有两步操作。

我们看一段Java原子性测试代码,使用AtomicInteger类实现对一个共享变量的递增操作。AtomicInteger类提供了compareAndSet方法,可以在多线程并发操作时保证对共享变量的修改都是原子性的

import java.util.concurrent.atomic.AtomicInteger;

public class AtomicTest implements Runnable {
    
    private AtomicInteger count = new AtomicInteger(0);
    
    public void run() {
        for (int i = 0; i < 10000; i++) {
            // 原子性自增
            count.incrementAndGet(); 
        }
    }
    //创建了两个线程,并在每个线程中执行10000次count.incrementAndGet()方法,
    //即对共享变量count进行原子性自增操作。最后在主线程中输出count的值
    public static void main(String[] args) throws InterruptedException {
        AtomicTest test = new AtomicTest();
        
        Thread thread1 = new Thread(test);
        Thread thread2 = new Thread(test);

        thread1.start();
        thread2.start();

        thread1.join();
        thread2.join();
        
        System.out.println("count=" + test.count.get());
    }
}

1.2 可见性

是指线程之间的可见性,一个线程修改的状态,对另一个线程是可见的。(也就是一个线程修改的结果,另一个线程能立马知道)。

在多线程并发编程中,由于每个线程都有自己线程栈和本地内存,因此存在一个问题:一个线程修改了共享变量的值,但是由于各种原因(比如缓存、处理器优化等),其他线程可能不会立即知道这个共享变量的最新值,这就导致了访问线程之间的数据不一致。

在java 中 synchronized、 final、 volatile实现可见性。

比如:使用volatile 修饰的变量,就具有可见性, volatile不允许线程内进行缓存和重排序,直接修改内存,所以对其他线程是可见的。

volatile虽然具有可见性,但不具有原子性:

eg:
我们定义一个变量,并进行 +1操作
volatile int i = 0;
i++;

此时i 具有可见性,但不具有原子性,如果多个线程同时对同一个volatile变量进行写操作,由于没有互斥机制,仍然会存在竞态条件问题。

1.3 有序性

程序执行时顺序按照代码但先后顺序执行。
在这里插入图片描述
比如下面这个,语句 1、2的顺序就可以调换, 3、4的则不行。

int a = 10;    //语句1
int r = 2;    //语句2
a = a + 3;    //语句3
r = a*a;     //语句4

二、线程安全

2.1、什么是线程安全

线程安全指内存的安全。这和操作系统有关,
在每个进程的内存空间中都会有一块特殊的公共区域,通常称为堆(内存)。
进程内的所有线程都可以访问到该区域,这就是造成问题的潜在原因。

所以线程安全指的是,在堆内存中的数据由于可以被任何线程访问到,
在没有限制的情况下存在被意外修改的风险。
即堆内存空间在没有保护机制的情况下,对多线程来说是不安全的地方,
因为你放进去的数据,可能被别的线程“破坏”。

2.2、为什么多线程不安全

进程中,有很多数据是多线程之间共享的,这些共享的数据很可能被其他线程修改了,那么线程之间共享了哪些进程资源呢?我们接着往下看,线程间数据的操作过程如下:

线程在执行时,先从主存中读取数据,然后复制一份到高速缓存中,
计算完后,再刷新到主存中。
 ____________      _______________
|cpu  高速缓存|   |  缓存一致性协议|
. -----------     |              |
|cpu  高速缓存|   |       or     |      主存
. -----------     |              |
|cpu  高速缓存|   |   总线锁机制   |
. -----------     |______________|

我们都知道进程是操作系统进行资源分配和调度的基本单位,线程thread是操作系统能够进行运算调度的最小单位,所以在某个进程里面,进程的所有资源对于这个进程里的所有线程来说是共享的,既然是共享的,所以在并发操作里,我们的数据就很有可能不安全,比如我们同时用两个线程对count1分别相加,等到的结果是不确定的。

2.2.1 哪些资源是线程私有的?

我们找到独属于线程的资源,其他的资源都是共享的,我们可以这么理解,线程运行的本质就是函数的执行,函数运行时的信息保存在栈帧中,栈帧中保存了函数的返回值、调用其它函数的参数、该函数使用的局部变量以及该函数使用的寄存器信息。

因此每个线程都有自己独立的、私有的栈区,
以上这些信息有一个统一的名字,就是线程上下文,thread context。

除此之外,剩下的都是线程间共享资源。
借用一张网络图片,如下
在这里插入图片描述

2.3 如何解决线程安全问题?

1、私有化
2、ThreadLocal
3、(互斥)锁
4、cas操作
等等

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/510804.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JavaScript经典教程(七)-- JavaScript初级

190&#xff1a;JavaScript初级内容 - DOM查询、插入内容、赋予样式等 1、DOM操作 DOM&#xff1a;节点&#xff0c;也就是html中的元素&#xff1b; DOM操作&#xff1a;其实就是节点元素的方法&#xff1b; &#xff08;1&#xff09;innerHTML - 返回元素内容 同时也可以…

【JUC基础】05. Synchronized和ReentrantLock

1、前言 前面两篇中分别讲了Synchronized和ReentrantLock。两种方式都能实现同步锁&#xff0c;且也都能解决多线程的并发问题。那么这两个有什么区别呢&#xff1f; 这个也是一个高频的面经题。 2、相同点 2.1、都是可重入锁 什么是可重入锁&#xff1f; 可重入锁&#xff0…

Mysql查询字符串中某个字符串出现的次数

目录 1.查单个字符出现的次数2.查多个字符出现的次数3.函数讲解 1.查单个字符出现的次数 比如我想查how do you do 字符串当中出现d的次数&#xff1a; 第一眼看上去有点懵&#xff0c;首先mysql并没有直接计算出现字符次数的函数&#xff0c;所以才使用了下面这种方式&#x…

【排错记录】国产航顺HK32F030M驱动TM1624四位数码管显示

问题描述&#xff1a; 航顺单片机 HK32F030MF4P6用数码管显示驱动TM1624问题描述。 航顺单片HK32F030MF4P6的PC3/PC4/PC5引脚分别连接数码管驱动TM1624的DIN/CLK/STB;当单独使用HK32F030MF4P6单片机最小系统和TM1624数码管模块的时候部分最小系统板能驱动数码管正常显示&…

Centos 7 安装系列(11):Kibana

一、系统环境 操作系统&#xff1a;Centos 7 已安装环境&#xff1a;ElasticSearch 8.6.2 二、安装 需要注意的是&#xff1a;Kibana的版本需要和Elasticsearch保持一致。 2.1 下载并解压安装包 cd /opt yum install -y wget wget https://artifacts.elastic.co/downloads…

马哈鱼SQLFLow对SQL Server OUTPUT Clause 的数据血缘分析

SQL Server OUTPUT Clause 会对 SQL 语句的血缘分析产生影响&#xff0c;如果忽略对 OUTPUT Clause 的分析&#xff0c;那么将漏掉一些关键的数据血缘关系&#xff0c;从而影响数据血缘分析的准确性&#xff0c;进而影响组织的数据治理质量。 Gudu SQLFlow 可以对 SQL Server …

Linux下安装MySQL 5.7

安装MySQL 5.7 1、通过命令下载 wget http://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.36-linux-glibc2.12-x86_64.tar.gz 2、解压 tar -zxvf mysql-5.7.36-linux-glibc2.12-x86_64.tar.gz -C /usr/local/mysql/ 3、简化 cd /usr/local mv mysql-5.7.36-linux-…

Hibernate 基本操作、懒加载以及缓存

前言 上一篇咱们介绍了 Hibernate 以及写了一个 Hibernate 的工具类&#xff0c;快速入门体验了一波 Hibernate 的使用&#xff0c;我们只需通过 Session 对象就能实现数据库的操作了。 现在&#xff0c;这篇介绍使用 Hibernate 进行基本的 CRUD、懒加载以及缓存的知识。 提示…

干货|做实验到底应该选取多少被试?

Hello&#xff0c;大家好&#xff01; 这里是壹脑云科研圈&#xff0c;我是喵君姐姐~ 我们都知道心理学实验一般是通过分析被试的一系列数据从而得到相应的结论的。那么&#xff0c;在进行心理学实验的时候需要多少被试&#xff1f;怎么去看实验的被试量够不够呢&#xff1f;…

【Spring Cloud】Spring Cloud Alibaba 实战 Seata (分布式事务)

文章目录 一、Seata 简介简要发展史Seata 设计初衷 二、使用 Docker 快速搭建 Seata 1.4三、在 Spring 项目中使用 Seata 客户端 一、Seata 简介 Seata&#xff08;Simple Extensible Autonomous Transaction Architecture&#xff09; 是一款开源的分布式事务解决方案&#xf…

Datawhale-chatGPT用于句词分类

NLU基础 句子级别的分类 Token级别的分类 相关API chatGPT Style prompt建议 NLU应用 文档问答 分类/实体微调 智能对话

php xdebug配置

1.sublime 火绒 火绒安装插件Xdebug Helper for Firefox 管理插件 -…-选项 填入ide key sublime 第一个插件package control ctrlshifitp 输入install 点击安装第一个包管理 package control 第二个插件 xdebug ctrlshifitp 输入xdebug clinet安装 php配置 这里用的时phps…

网安笔记03 DES概述

DES 概述 分组加密算法 &#xff1a; 明文、密文64位分组长度对称算法 &#xff1a; 加密和解密密钥编排不同&#xff0c;但使用同一算法密钥长度&#xff1a;56位 —— 每个第8位为奇偶校验位密钥为任意的56位数&#xff0c;存在 弱密钥&#xff0c; 容易避开混乱与扩散的组合…

初学者自学Web安全的三个必经阶段(含系统路线脑图+工具笔记)

一、为什么选择网络安全&#xff1f; 这几年随着我国《国家网络空间安全战略》《网络安全法》《网络安全等级保护2.0》等一系列政策/法规/标准的持续落地&#xff0c;网络安全行业地位、薪资随之水涨船高。 未来3-5年&#xff0c;是安全行业的黄金发展期&#xff0c;提前踏入…

React学习1

JSX使得创建虚拟DOM更便捷&#xff0c;纯JS创建虚拟DOM太过繁琐 JSX语法规范&#xff1a; JSX的{}&#xff0c;读变量的时候只能存放表达式&#xff0c;不能写语句&#xff08;代码&#xff09; react可以遍历数组&#xff0c;但是无法遍历对象 react是面向组件编程 函数式…

5月10号软件资讯更新合集....

elementary OS 图像注释工具 Annotator 1.2 发布 Annotator 是一个免费开源图像注释工具&#xff0c;最初是为 elementary OS 设计&#xff0c;但也可用于其他 Linux。近日该工具发布了 1.2 版本&#xff0c;新版本增加了对全屏、当前窗口和选择区域进行截图等功能。 新版本还…

Dcoker高级篇

一、复杂安装详细说明 &#xff08;一&#xff09;安装mysql主从复制 主从复制原理 原理&#xff1a; &#xff08;1&#xff09;master服务器将数据的改变记录二进制binlog日志&#xff0c;当master上的数据发生改变时&#xff0c;则将其改变写入二进制日志中&#xff1b;&…

quill编辑器自定义音频、视频、行内style样式(字符边框、首行缩进)

文章目录 一、音频1、自定义内容2、引入使用 二、视频1、自定义内容2、引入使用 三、文本添加行内style样式&#xff08;文本边框&#xff09;1、不带有下拉框&#xff08;1&#xff09;自定义内容&#xff08;2&#xff09;引入使用 2、带有下拉框&#xff08;1&#xff09;自…

【SpringCloud】Nacos安装与入门

目录 一、认识与安装 1、访问 2、下载 3、解压 4、启动 5、访问 二、基本使用 1、搭建服务 2、服务注册 3、服务发现 一、认识与安装 他是阿里巴巴的产品&#xff0c;也是SpringCloud中的一个注册中心组件&#xff0c;其功能相比Eureka更丰富&#xff0c;在国内更受欢…

设计师常用的7款界面设计工具!

不同的界面设计工具都有其独特的优点和不足之处。本文为大家介绍设计师常用的7款界面设计工具&#xff1a;即时设计是一款在线UI界面设计工具&#xff0c;拥有中文界面和丰富的社区资源&#xff0c;适合初学者和专业设计师使用。Sketch具有直观的矢量编辑工具和可重复使用的符号…