【多线程】线程的可见性

news/2024/11/7 22:41:12/

目录

        • 一、什么是线程的可见性
        • 二、可见性问题示例
          • 2.1 代码
          • 2.2 截图
        • 三、解决可见性问题
          • 3.1 volatile关键字
          • 3.2 synchronized关键字
        • 四、用volatile关键字解决可见性问题示例
          • 4.1 代码
          • 4.2 截图
        • 五、用synchronized关键字解决可见性问题示例
          • 5.1 代码
          • 5.2 截图
        • 六、可见性与原子性

一、什么是线程的可见性

  • 1.当一个线程修改了共享变量的值,其他线程会马上知道这个修改。当其他线程要读取这个变量的时候,最终会去内存中读取,而不是从缓存中读取
  • 2.一个线程对共享变量的修改,另一个线程可以感知到,称为可见性
  • 3.在CPU中存在MESI协议,即缓存的一致性协议:一个线程修改变量,CPU会刷新缓存,并刷新回内存,线程2得知线程1修改变量,cpu2通过总线嗅探机制,会重新去内存中加载变量a

二、可见性问题示例

2.1 代码
package com.learning.visibility;/*** @Description 可见性学习*/
public class VisibilityLearning {static boolean run = true;public static void main(String[] args) throws InterruptedException {Thread thread = new Thread(()->{while(run){System.out.println("thread没有停止");}});thread.start();Thread.sleep(1000);System.out.println("主线程停止thread");run = false;}
}
2.2 截图

在这里插入图片描述

三、解决可见性问题

3.1 volatile关键字
  • 1.使用volatile [ˈvɑːlətl]关键字修饰变量
  • 2.volatile 易变关键字
  • 3.可以用来修饰成员变量和静态成员变量
  • 4.可以避免线程从自己的工作缓存中查找变量的值,必须从主存中获取变量的值,线程操作volatile变量都是直接操作主存
3.2 synchronized关键字
  • 1.synchronized关键字会清空工作内存,代码块结束后将更改后的共享变量的值刷新到主内存中

四、用volatile关键字解决可见性问题示例

4.1 代码
package com.learning.visibility;/*** @Description 可见性学习*/
public class VisibilityLearning {volatile static boolean run = true;public static void main(String[] args) throws InterruptedException {Thread thread = new Thread(()->{while(run){System.out.println("thread没有停止");}});thread.start();Thread.sleep(1000);System.out.println("主线程停止thread");run = false;}
}
4.2 截图

在这里插入图片描述

五、用synchronized关键字解决可见性问题示例

5.1 代码
package com.learning.visibility;/*** @Description 可见性学习*/
public class VisibilityLearning {static boolean run = true;//锁对象final static Object lock = new Object();public static void main(String[] args) throws InterruptedException {Thread thread = new Thread(()->{while(true){synchronized (lock){System.out.println("thread没有停止");if(!run){break;}}}});thread.start();Thread.sleep(1000);System.out.println("主线程停止thread");synchronized (lock){run = false;}}
}
5.2 截图

在这里插入图片描述

六、可见性与原子性

  • 1.一个线程对volatile变量的修改对另一个线程可见,不能保证原子性,仅用在一个写线程,多个读线程的情况
  • 2.volatile只能保证看到最新值,不能解决指令交错
  • 3.synchronized语句块既可以保证代码块的原子性,也同时保证代码块内变量的可见性,缺点是synchronized是属于重量级的操作,性能相对更低

http://www.ppmy.cn/news/83286.html

相关文章

放大镜-第14届蓝桥杯省赛Scratch中级组真题第3题

[导读]:超平老师的《Scratch蓝桥杯真题解析100讲》已经全部完成,后续会不定期解读蓝桥杯真题,这是Scratch蓝桥杯真题解析第138讲。 放大镜,本题是2023年5月7日举行的第14届蓝桥杯省赛Scratch图形化编程中级组编程第3题&#xff0…

Linux系统安装Redis

1.远程下载稳定版本 wget http://download.redis.io/releases/redis-6.0.7.tar.gz 编译 redis-6.x,要求 C11 编译器(因为redis是用c写的),否则会遇到大量如下所示的错误: server.h:1051:5: 错误:expected…

音视频八股文(6)-- ffmpeg大体介绍和内存模型

播放器框架 常用音视频术语 • 容器/文件(Conainer/File):即特定格式的多媒体文件, 比如mp4、flv、mkv等。 • 媒体流(Stream):表示时间轴上的一段连续数据,如一 段声音…

整合Springboot+MybatisPlus+达梦数据库

1、安装Windows环境的达梦数据库可视化软件 这里不做安装介绍 安装步骤很简单,提供的软件也很全面,特别是数据库迁移工具,支持市面上许多主流的大型数据库,例如:Oracle、SQLServer、MySQL、DB2、PostgreSQL、Informix…

centos下编译ffmpeg+ libfdk_aac +x264

因为FFmpeg自带的AAC编码器已经废弃了AV_SAMPLE_FMT_S16格式PCM编码AAC,如果使用FFmpeg自带的AAC编码器,就需要做音频的重采样(AV_SAMPLE_FMT_S16重采样为:AV_SAMPLE_FMT_FLTP), 如果不想自己做重采样转换,可以使用libfdk-aac这库。 编译FFMPEG之前,先编译好libfdk-aac…

openldap介绍以及使用

参考文献:openldap介绍和使用 基本概念 官网:https://www.openldap.org 官方文档:https://www.openldap.org/doc LDAP是一个开放的,中立的,工业标准的应用协议,通过IP协议提供访问控制和维护分布式信息的…

【星戈瑞】BODIPY-530/550氟化硼二吡咯荧光染料

BODIPY是一种荧光染料,其分子结构稳定、荧光强度高、荧光寿命长、光谱范围广,因此在许多领域都有应用。在生物医学领域,BODIPY作为荧光探针,可用于细胞成像、生物分子探测、药物筛选等方面。例如,一些研究者将BODIPY修…

Vue3:组件基础(下)

Vue3:组件基础(下) Date: April 12, 2023 Sum: props验证、计算属性、自定义时间、组件上的v-model、任务列表案例 目标: 能够知道如何对 props 进行验证 能够知道如何使用计算属性 令能够知道如何为组件自定义事件 令能够知…