JUC并发编程-第二天:线程高级部分

news2024/12/22 9:58:10

线程高级部分

    • 线程不安全
    • 原子性
    • 可见性
    • 有序性(指令重排)
    • 更多的解决线程安全

线程不安全

多线程下并发同时对共享数据进行读写,会造成数据混乱=线程不安全

当多线程下并发访问临界资源时,如果破坏其原子性、可见性、有序性,可能会造成数据不一致。

原子性

原子性操作指相应的操作是 单一不可分割的操作。

可见性

指当多个线程访问同一个资源时,一个线程修改了资源,其他线程能够立即看到修改的值

  • 比如下面的代码就违反了可见性
public class ThreadPool {
    static boolean alwasy=true;
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        new Thread(()->{
            while (alwasy){

            }
        }).start();

        Thread.sleep(2000);
        alwasy=false;
    }
}

原因:两个线程共享主内存变量,复制了两份副本,我们改变的只是主线程的变量 另外一个线程的没有改过来。主内存改了后并不会同步到主内存中。
在这里插入图片描述

  • 解决方法:使用synchronized ,synchronized 在解锁之前会将变量同步到主内存中
public class ThreadPool {
    static Boolean alwasy=true;
    
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        new Thread(()->{
            while (alwasy){
                synchronized (alwasy){

                }
            }
        }).start();

        Thread.sleep(2000);
        alwasy=false;
    }
}

对一个变量解锁之前,必须先把此变量同步回主内存中,这样解锁后,线程就可以访问被修改后的值
所以synchronized 锁住的对象,其值具有可见性

  • 非常重要
    使用 System.out.println();也可以的,因为System.out.println();里面也实现了synchronized 锁
    在这里插入图片描述
    synchronized的锁,任意一个被锁住的对象,只要锁释放了,就会把工作内存中变量同步到主内存
public class ThreadPool {
    static Boolean alwasy=true;

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        new Thread(()->{
            while (alwasy){
                //这个也可以
                System.out.println();
            }
        }).start();

        Thread.sleep(2000);
        alwasy=false;
    }
}

有序性(指令重排)

有序性最终表述的现象是CPU是否按照既定代码顺序一次执行指令。

CPU和编译器为了提高指令的执行效率可能会进行指令重新排序,这使得代码的实际执行方式可能不是按照我们所认为的方式进行。
在单线程的情况下只要保证最终执行结果正确即可。如下
在这里插入图片描述
在单线程的情况下这没问题。多线程的情况下就出问题了。如下代码:

public class Order_Test {
    static ThreadPool threadPool;
    static Boolean isInit=false;

    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 1000000; i++) {
            isInit=false;
            threadPool=null;

            Thread t1=new Thread(()->{
                threadPool=new ThreadPool();
                isInit=true;
            });

            Thread t2=new Thread(()->{
                 if (isInit){
                     threadPool.doSomething();
                 }
            });

            t1.start();
            t2.start();

            t1.join();
            t2.join();
        }
    }
}

两个线程t1,t2同时运行,t2依赖t1,如果t1指令重排,isInit先设置为true,threadPool没有被初始化。此时t2同时运行,进入if,threadPool为空此时报空指针异常

在执行t1的时候可能会指令重排成这个样子

 Thread t1=new Thread(()->{
                isInit=true;
                threadPool=new ThreadPool();
            });
  • 解决指令重排导致的问题:用synchronized锁,让两个线程串行执行,
    两个线程同时进来,先抢到锁的先执行,执行完毕后另一个再执行,此时串行执行
public class Order_Test {
    static ThreadPool threadPool;
    static Boolean isInit=false;

    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 1000000; i++) {
            isInit=false;
            threadPool=null;

            Thread t1=new Thread(()->{
                synchronized (isInit){
                    threadPool=new ThreadPool();
                    isInit=true;
                }
            });

            Thread t2=new Thread(()->{
                synchronized (isInit){
                    if (isInit){
                        threadPool.doSomething();
                    }
                }
            });

            t2.start();
            t1.start();

            t2.join();
            t1.join();
        }
    }
}

更多的解决线程安全

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

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

相关文章

账号和权限的管理

文章目录 管理用户账号和组账号用户账号的分类超级用户普通用户程序用户 UID&#xff08;用户id)和(组账号)GIDUID用户识别号GID组标识号 用户账号文件添加用户账号设置/更改用户口令 管理用户账号和组账号 用户账号的分类 超级用户 root 用户是 Linux 操作系统中默认的超级…

《米小圈动画汉字》汉字教育动画化:传统与创新的完美融合!

汉字&#xff0c;作为中华文化的瑰宝&#xff0c;承载着千百年来中华民族的智慧和思想。每一个汉字不仅仅是一个符号&#xff0c;更是一段历史的见证&#xff0c;一种文化的传承。在当今全球化的背景下&#xff0c;汉字教育面临着新的挑战与机遇。在这种背景下&#xff0c;如何…

LabVIEW程序退出后线程仍在运行问题

LabVIEW程序退出后&#xff0c;线程仍在运行的问题可能源于资源管理不当、未正确终止循环、事件结构未处理、并发编程错误以及外部库调用未结束等方面。本文将从这些角度详细分析&#xff0c;探讨可能的原因和解决方案&#xff0c;并提供预防措施&#xff0c;帮助开发者避免类似…

FPGA PCIe加载提速方案

目录 1.bit流压缩 2.flash加载速度 3.Tandem模式 1.bit流压缩 set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design] 2.flash加载速度 打开bitstream setting&#xff0c;设置SPI的线宽和速率&#xff08;线宽按原理图设置&#xff0c;速率尽可能高&#xff09…

redis-基础篇(2)

黑马redis-基础篇笔记 3. redis的java客户端-Jedis 在Redis官网中提供了各种语言的客户端&#xff0c;地址&#xff1a;https://redis.io/docs/clients/ 标记为❤的就是推荐使用的java客户端&#xff0c;包括&#xff1a; Jedis和Lettuce&#xff1a;这两个主要是提供了Redi…

Vant2组件库的基础应用

目录 一、Picker 选择器 1.1、数组对象处理 1.2、每个选项颜色设置 二、滚动分页加载列表 三、Calendar 日历(可选范围限制) 四、input值过滤 官网&#xff1a;Vant 2 - Mobile UI Components built on Vue 一、Picker 选择器 官网示例数据&#xff1a; columns: [杭州…

有趣的 Oracle JDBC 驱动包命名问题 - ojdbc6 和 ojdbc14 哪个新?!

有趣的 Oracle JDBC 驱动包命名问题 - ojdbc6 和 ojdbc14 哪个新?! 1 背景概述 最近协助一个小兄弟排查了某作业使用 sqoop 采集 oracle 数据的失败问题&#xff0c;问题现象&#xff0c;问题原因和解决方法都挺直观&#xff0c;但在此过程中发现了一个有趣的 Oracle JDBC 驱…

JAVA每日作业day6.20

ok了家人们&#xff0c;今天学习了面向对象的继承&#xff0c;话不多说让我们看看怎么个事。 我们先把昨天学 面向对象-封装 的温习一下&#xff0c;来个例子 1&#xff0c;综合案例 做一个关于学生的随机点名器 定义了两个变量&#xff0c;name和age&#xff0c;给他们封装一…

java封装模块为jar包- FUSE 智能BPM低代码平台-企业级

第一种方法 将打好的项目模块jar放入lib文件夹内 操作后 项目便有了此jar包的依赖 第二种方法 使用 maven引入 可以参考我之前发的博客 IDEA导入jar包_idea导入jar包方法-CSDN博客

简单分享github

一、官网 GitHub: Let’s build from here GitHub 二、注册 通过简单的注册步骤&#xff0c;你就可以拥有一个属于自己的GitHub账号。再简单注册完成之后会需要验证你所输入的邮箱才能正常使用你的GitHub。 三、设置自己的库 在注册完成之后&#xff0c;完成一些简单的设置之…

PS给logo加白色描边

步骤1&#xff1a;打开你的Logo文件 步骤2&#xff1a;选择Logo层 在“图层”面板中找到你的Logo所在的图层。如果你的Logo是在背景图层上&#xff0c;可以将它转换为普通图层&#xff08;右键点击背景图层&#xff0c;选择“从背景图层转换”&#xff09;&#xff08;此处也…

【转载】TIOBE 编程指数 6 月排行榜公布,vb.net排第九

原文地址&#xff1a;https://baijiahao.baidu.com/s?id1801368030428902126&wfrspider&forpc IT之家 6 月 9 日消息&#xff0c;TIOBE 编程社区指数是一个衡量编程语言受欢迎程度的指标&#xff0c;评判的依据来自世界范围内的工程师、课程、供应商及搜索引擎&#…

【服务器02】之阿里云平台

百度一下阿里云官网 点击注册直接使用支付宝注册可以跳过认证 成功登录后&#xff0c;点击产品 点击免费试用 点击勾选 选一个距离最近的 点满GB 注意&#xff1a;一般试用的时用的是【阿里云】&#xff0c;真正做项目时用的是【腾讯云】 现在开始学习使用&#xff1a; 首先…

Samtec制造理念系列二 | 差异变量管理的意义与挑战

【摘要/前言】 制造高端电子产品是非常复杂精密的过程。制作用于演示或原型的一次性样品可能具有挑战性&#xff0c;但真正的挑战在于如何以盈利的方式持续生产。 这就是Samtec风险投资研发工程总监Aaron Tucker在一次关于生产高密度微小型连接器的挑战的演讲中所强调的观点。…

使用宝塔面板搭建Flask项目保姆级喂饭教程

目录 零.前言 一.准备工作 1.1创建requirements.txt文件 1.2将项目打包为压缩文件 1.3租一台服务器 1.4部署宝塔面板 二.宝塔面板(服务器)上的操作 2.1将本地Flask项目上传到服务器 2.2添加Python项目 2.3配置Python项目 2.4配置Nginx 2.5宝塔面板放行端口 2.6在服…

2024年一建报名汇总和常见问题答疑!

2024年一级建造师报名通知全国32个地区均已发布&#xff0c;考试100汇总如下&#xff0c;大家务必及时报名&#xff0c;千万不要错过&#xff01; ​ 报名问题 01、时间不多了&#xff0c;今年可以先考部分学科吗&#xff1f;分两年考完&#xff1f; 可以的&#xff0c;一建…

视觉SLAM14精讲——相机与图像3.3

视觉SLAM14精讲 三维空间刚体运动1.0三维空间刚体运动1.1三维空间刚体运动1.2李群与李代数2.1相机与图像3.1相机与图像3.2 视觉SLAM14精讲——相机与图像3.3 视觉SLAM14精讲相机投影流程双目相机模型 相机投影流程 至此&#xff0c;有关相机三维刚体变换的所有因素已经汇集。…

朗科HD10M2Pr震撼上市,自带风扇极速降温,匹敌私有云

近日,存储领域的领军企业朗科旗下全资子公司朗科创新宣布,其最新款磁吸硬盘盒HD10M2Pr正式上市。这款产品凭借超薄设计、极速降温、高速传输等多项优势,迅速成为了行业内的讨论焦点。 随着移动设备使用的普及和短视频内容的日益丰富,对于存储空间不断增长的需求逐渐成为日常生活…

react项目中如何书写css

一&#xff1a;问题&#xff1a; 在 vue 项目中&#xff0c;我们书写css的方式很简单&#xff0c;就是在 .vue文件中写style标签&#xff0c;然后加上scope属性&#xff0c;就可以隔离当前组件的样式&#xff0c;但是在react中&#xff0c;是没有这个东西的&#xff0c;如果直…

如何解决windows自动更新,释放C盘更新内存

第一步&#xff1a;首先关闭windows自动更新组件 没有更新windows需求&#xff0c;为了防止windows自动更新&#xff0c;挤占C盘空间&#xff0c;所以我们要采取停止Windows Update服务。按下WinR打开运行对话框&#xff0c;输入services.msc&#xff0c; 然后按Enter。在服务…