Java多线程——线程安全性

news2025/1/31 0:45:30

线程安全性

当多个线程访问某个类时,这个类始终都能表现出正确的行为,那么就称这个类是线程安全的

public class A {

    public void test(){
        //....
    }
}

无状态对象是线程安全的,其不包含任何域,也不包含任何对其他类中域的引用,调用过程产生的临时状态也仅存在于线程栈上的局部变量中

竞态条件

public class A {

    private long count;

    public long getCount() {
        return count;
    }

    public void test() {
        //....
        count++;
    }
}

如果新增计数器记录方法调用次数,此时类变为非线程安全,对于“读取-修改-写入”复合操作过程,两个线程执行情况可能如下
在这里插入图片描述

由于不同的运行顺序会导致不一样的结果,称为竞态条件

原子性操作

对于访问同一个状态的所有操作(包括该操作本身)来说,这个操作是一个以原子方式执行的操作

public class A {

    private AtomicLong count;

    public long getCount() {
        return count.get();
    }

    public void test() {
        //....
        count.incrementAndGet();
    }
}

可使用原子变量类AtomicLong代替long确保所有对count的操作是原子性

内置锁

若两个原子变量相互影响,则又可能出现竞态条件,如下count为0时,线程1和2同时新增了count,但线程1再调用getCount()已为2导致错误

public class A {

    private AtomicLong count;
    private AtomicBoolean isOdd;

    public long getCount() {
        return count.get();
    }

    public void test() {
        //....
        count.incrementAndGet();
        isOdd.set(getCount() % 2 == 0);
    }
}

此时需要使用如下同步代码块,其包含两个部分

  • 作为锁的对象引用,每个java对象都可作为锁,称为内置锁
  • 这个锁保护的代码块
synchronized(lock){
	......
}

synchronized修饰方法时

  • 整个方法体为同步代码块
  • 锁就是方法调用所在的对象,若是static方法则以class对象作为锁

如上,可添加synchronized让两个变量的修改具有原子性

public class A {
	
	@GuardedBy("this")
    private Long count;
	
	@GuardedBy("this")
    private Boolean isOdd;

    public long getCount() {
        return count;
    }

    public synchronized void test() {
        //....
        count++;
        isOdd = getCount() % 2 == 0;
    }
}

内置锁是可重入的,即线程可以获得一个已经由它自己持有的锁(synchronized方法可互相调用),锁的颗粒度是线程而不是调用

活跃性与性能

上面用synchronized加锁方法可以保证原子性,但每次只有一个线程可以执行(即线程1调用了对象的synchronized方法,线程2想要调用其他synchronized方法时需等线程1释放锁),若方法耗时过长则会影响性能

public class A {

    @GuardedBy("this")
    private Long count;
    @GuardedBy("this")
    private Boolean isOdd;

    public long getCount() {
        return count;
    }

    public void test() {
        //....
        synchronized (this) {
            count++;
            isOdd = getCount() % 2 == 0;
        }
    }
}

如上,缩小锁的范围,只限制共享变量,避免其他操作同步

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

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

相关文章

Windows安装Miniconda和PySide6以及配置PyCharm

目录 1. 选择Miniconda 2. 下载Miniconda 3. 安装Miniconda 4. 在base环境下创建pyside6环境 5. 安装pyside6环境 6. 配置PyCharm环境 7. 运行第一个程序效果 1. 选择Miniconda 选择Miniconda而没有选择Anaconda,是因为它是一个更小的Anaconda发行版&#x…

C++传送锚点的内存寻址:内存管理

文章目录 1.C/C内存分布回顾2.C内存管理2.1 内存申请2.2 operator new与operator delete函数2.3 定位new表达式 3.关于内存管理的常见知识点3.1 malloc/free和new/delete的区别3.2 内存泄漏 希望读者们多多三连支持小编会继续更新你们的鼓励就是我前进的动力! 继C语…

循序渐进kubernetes-RBAC(Role-Based Access Control)

文章目录 概要Kubernetes API了解 Kubernetes 中的 RBACRoles and Role Bindings:ClusterRoles and ClusterRoleBindings检查访问权限:外部用户结论 概要 Kubernetes 是容器化应用的强大引擎,但仅仅关注部署和扩展远远不够,集群的安全同样至…

《从因果关系的角度学习失真不变表示以用于图像恢复》学习笔记

paper:2303.06859 GitHub:lixinustc/Causal-IR-DIL: Distortion invariant feature learning for image restoration from a causality perspective 2023 CVPR 目录 摘要 1、介绍 1.1 图像修复任务 1.2 失真不变表示学习 1.3 因果效应估计的挑战…

亚博microros小车-原生ubuntu支持系列:16 机器人状态估计

本来想测试下gmapping建图,但是底层依赖了yahboomcar_bringup做底层的数据处理,所以先把依赖的工程导入。 程序启动后,会订阅imu和odom数据,过滤掉一部分的imu数据后,然后与odom数据进行融合,最后输出一个…

Greenplum临时表未清除导致库龄过高处理

1.问题 Greenplum集群segment后台日志报错 2.回收库龄 master上执行 vacuumdb -F -d cxy vacuumdb -F -d template1 vacuumdb -F -d rptdb 3.回收完成后检查 仍然发现segment还是有库龄报警警告信息发出 4.检查 4.1 在master上检查库年龄 SELECT datname, datfrozen…

【Unity3D】实现横版2D游戏角色二段跳、蹬墙跳、扶墙下滑

目录 一、二段跳、蹬墙跳 二、扶墙下滑 一、二段跳、蹬墙跳 GitHub - prime31/CharacterController2D 下载工程后直接打开demo场景:DemoScene(Unity 2019.4.0f1项目环境) Player物体上的CharacterController2D,Mask添加Wall层…

mybatis(134/134)完结

一级缓存(默认情况下开启)同一个sqlsession中执行相同的查询语句走一级缓存 二级缓存 :同一个sqlsessionfactory,sqlsession关闭了才会将一级缓存提交到二级缓存中 外部编写的缓存 PageHelper插件:方便进行分页&#x…

PaddleSeg 从配置文件和模型 URL 自动化运行预测任务

git clone https://github.com/PaddlePaddle/PaddleSeg.git# 在ipynb里面运行 cd PaddleSegimport sys sys.path.append(/home/aistudio/work/PaddleSeg)import os# 配置文件夹路径 folder_path "/home/aistudio/work/PaddleSeg/configs"# 遍历文件夹,寻…

BLE透传方案,IoT短距无线通信的“中坚力量”

在物联网(IoT)短距无线通信生态系统中,低功耗蓝牙(BLE)数据透传是一种无需任何网络或基础设施即可完成双向通信的技术。其主要通过简单操作串口的方式进行无线数据传输,最高能满足2Mbps的数据传输速率&…

苍穹外卖—订单模块

该模块分为地址表的增删改查、用户下单、订单支付三个部分。 第一部分地址表的增删改查无非就是对于单表的增删改查,较基础,因此直接导入代码。 地址表 一个用户可以有多个地址,同时有一个地址为默认地址。用户还可为地址添加例如&q…

openeuler 22.03 lts sp4 使用 cri-o 和 静态 pod 的方式部署 k8s-v1.32.0 高可用集群

前情提要 整篇文章会非常的长…可以选择性阅读,另外,这篇文章是自己学习使用的,用于生产,还请三思和斟酌 静态 pod 的部署方式和二进制部署的方式是差不多的,区别在于 master 组件的管理方式是 kubectl 还是 systemctl有 kubeadm 工具,为什么还要用静态 pod 的方式部署?…

MySQL分表自动化创建的实现方案(存储过程、事件调度器)

《MySQL 新年度自动分表创建项目方案》 一、项目目的 在数据库应用场景中,随着数据量的不断增长,单表存储数据可能会面临性能瓶颈,例如查询、插入、更新等操作的效率会逐渐降低。分表是一种有效的优化策略,它将数据分散存储在多…

接口技术-第6次作业

目录 作业内容 解答 1.假设在一个系统中,8255A的端口地址为184H-187H,A口工作于方式1输出,B口工作于方式1输入,禁止中断,C口剩余的两根线PC5,PC4位输入,如下图所示,试编写初始化…

(1)Linux高级命令简介

Linux高级命令简介 在安装好linux环境以后第一件事情就是去学习一些linux的基本指令,我在这里用的是CentOS7作演示。 首先在VirtualBox上装好Linux以后,启动我们的linux,输入账号密码以后学习第一个指令 简介 Linux高级命令简介ip addrtou…

网络直播时代的营销新策略:基于受众分析与开源AI智能名片2+1链动模式S2B2C商城小程序源码的探索

摘要:随着互联网技术的飞速发展,网络直播作为一种新兴的、极具影响力的媒体形式,正逐渐改变着人们的娱乐方式、消费习惯乃至社交模式。据中国互联网络信息中心数据显示,网络直播用户规模已达到3.25亿,占网民总数的45.8…

CSS(快速入门)

欢迎大家来到我的博客~欢迎大家对我的博客提出指导,有错误的地方会改进的哦~点击这里了解更多内容 目录 一、什么是CSS?二、基本语法规范三、CSS选择器3.1 标签选择器3.2 id选择器3.3 class选择器3.4 通配符选择器3.5 复合选择器 四、常用CSS样式4.1 color4.2 font…

对顾客行为的数据分析:融入2+1链动模式、AI智能名片与S2B2C商城小程序的新视角

摘要:随着互联网技术的飞速发展,企业与顾客之间的交互方式变得日益多样化,移动设备、社交媒体、门店、电子商务网站等交互点应运而生。这些交互点不仅为顾客提供了便捷的服务体验,同时也为企业积累了大量的顾客行为数据。本文旨在…

MySQL查询优化(三):深度解读 MySQL客户端和服务端协议

如果需要从 MySQL 服务端获得很高的性能,最佳的方式就是花时间研究 MySQL 优化和执行查询的机制。一旦理解了这些,大部分的查询优化是有据可循的,从而使得整个查询优化的过程更有逻辑性。下图展示了 MySQL 执行查询的过程: 客户端…

UE AController

定义和功能 AController是一种特定于游戏的控制器,在UE框架中用于定义玩家和AI的控制逻辑。AController负责处理玩家输入,并根据这些输入驱动游戏中的角色或其他实体的行为。设计理念 AController设计用于分离控制逻辑与游戏角色,增强游戏设计…