当前位置: 首页 > news >正文

理解线程的三大特性:原子性、可见性和有序性

        在并发编程中,保护线程安全是一个重要课题。要实现线程安全,我们必须理解并掌握三个核心概念:原子性、可见性和有序性。下面将详细介绍这三个特性及其解决方案。

一、原子性

        原子性是指一个操作要么全部完成,要么完全不执行。在多线程环境中,原子性确保了数据操作的完整性。例如,在银行账户转账时,从一个账户转出资金并立即转入另一个账户,这两个操作必须连贯执行,不可中断。    

解决方案

在Java中,使用synchronized关键字可以实现原子性。

代码示例
public class AtomicCounter {private int count = 0; // 计数器// 使用 synchronized 确保原子性public synchronized void increment() {count++; // 增加计数}public synchronized int getCount() {return count; // 获取计数值}public static void main(String[] args) throws InterruptedException {AtomicCounter counter = new AtomicCounter();Thread thread1 = new Thread(() -> {for (int i = 0; i < 1000; i++) {counter.increment();}});Thread thread2 = new Thread(() -> {for (int i = 0; i < 1000; i++) {counter.increment();}});thread1.start();thread2.start();thread1.join();thread2.join();System.out.println("最终计数值: " + counter.getCount()); // 应输出2000}
}

二、可见性

        可见性是指一个线程对共享变量的修改能够及时被其他线程看到。在某些情况下,线程可能在本地缓存中读取变量,导致读取到旧的值。

解决方案

        使用volatile关键字可以解决可见性问题。被声明为volatile的变量会确保在多线程中所有线程都能看到最新的值。

代码示例
public class VolatileExample {private volatile boolean running = true; // 控制线程的标志public void start() {Thread thread = new Thread(() -> {while (running) {System.out.println("线程运行中...");}System.out.println("线程已停止");});thread.start();try {Thread.sleep(1000); // 等待一段时间} catch (InterruptedException e) {e.printStackTrace();}running = false; // 修改标志位}public static void main(String[] args) {VolatileExample example = new VolatileExample();example.start(); // 启动线程}
}

三、有序性

        有序性是指程序操作的执行顺序与代码中书写的顺序一致。在多线程环境中,指令重排序可能导致预期的执行顺序被打乱,从而引发错误。

解决方案

通过使用synchronizedvolatile来控制有序性,确保重要操作按照预期顺序执行。

代码示例
public class OrderingExample {private int a = 0;private int b = 0;private int x = 0;private int y = 0;public void write() {a = 1; // 操作1x = b; // 操作2}public void read() {b = 1; // 操作3y = a; // 操作4}public void execute() throws InterruptedException {Thread thread1 = new Thread(this::write);Thread thread2 = new Thread(this::read);thread1.start();thread2.start();thread1.join();thread2.join();System.out.println("x: " + x + ", y: " + y);}public static void main(String[] args) throws InterruptedException {OrderingExample example = new OrderingExample();example.execute(); // 可能输出 "x: 0, y: 0"(不保证顺序)}
}

  • 原子性:使用synchronized确保多个线程对共享变量的操作是原子的,从而避免数据竞争。
  • 可见性:使用volatile确保一个线程对变量的修改能够被其他线程及时看到,避免从本地缓存中读取过期值。
  • 有序性:使用synchronizedvolatile防止编译器和处理器对指令进行重排序,确保操作的执行顺序与代码中书写的顺序一致。

四、锁的使用

        锁是一种同步机制,可以控制多个线程对共享资源的访问,从而确保操作的原子性和可见性。在Java中,有多种锁的类型,但最常用的是ReentrantLocksynchronized关键字。

1. ReentrantLock

   ReentrantLock是Java提供的显式锁,功能更加灵活,支持公平锁与非公平锁。使用ReentrantLock需要手动加锁和释放锁。

代码示例
import java.util.concurrent.locks.ReentrantLock;public class LockExample {private int count = 0; // 计数器private ReentrantLock lock = new ReentrantLock(); // 创建锁public void increment() {lock.lock(); // 加锁try {count++; // 增加计数} finally {lock.unlock(); // 确保释放锁}}public int getCount() {return count; // 获取计数值}public static void main(String[] args) throws InterruptedException {LockExample example = new LockExample();Thread thread1 = new Thread(() -> {for (int i = 0; i < 1000; i++) {example.increment();}});Thread thread2 = new Thread(() -> {for (int i = 0; i < 1000; i++) {example.increment();}});thread1.start();thread2.start();thread1.join();thread2.join();System.out.println("最终计数值: " + example.getCount()); // 应输出2000}
}

2. synchronized

   synchronized是Java中内置的同步机制,它简单易用,可以直接通过关键字来实现线程安全。在方法上使用时,它会锁住该方法的对象实例;在代码块上使用时,可以指定需要锁住的对象。

代码示例
public class SynchronizedExample {private int count = 0; // 计数器// 使用 synchronized 关键字确保原子性public synchronized void increment() {count++; // 增加计数}public synchronized int getCount() {return count; // 获取计数值}public static void main(String[] args) throws InterruptedException {SynchronizedExample example = new SynchronizedExample();Thread thread1 = new Thread(() -> {for (int i = 0; i < 1000; i++) {example.increment();}});Thread thread2 = new Thread(() -> {for (int i = 0; i < 1000; i++) {example.increment();}});thread1.start();thread2.start();thread1.join();thread2.join();System.out.println("最终计数值: " + example.getCount()); // 应输出2000}
}

五、锁的优缺点

  • 优点

    • 灵活性ReentrantLock提供了更高的灵活性,比如可以尝试获取锁、设置锁的超时时间等。
    • 可中断:线程在等待获取锁时,可以响应中断,这在某些情况下非常有用。
  • 缺点

    • 复杂性:需要显式释放锁,容易因代码错误导致死锁。
    • 性能开销:相比synchronized,显式锁会引入较大的性能开销。

总结

        在多线程编程中,为了确保原子性、可见性和有序性,我们可以使用锁(如synchronizedReentrantLock)来保护共享资源。理解和灵活运用锁,是进行并发编程的必备技能。无论选择哪种锁,都应确保在执行完关键操作后及时释放锁,以防止潜在的死锁问题和资源浪费。

相关文章:

理解线程的三大特性:原子性、可见性和有序性

在并发编程中&#xff0c;保护线程安全是一个重要课题。要实现线程安全&#xff0c;我们必须理解并掌握三个核心概念&#xff1a;原子性、可见性和有序性。下面将详细介绍这三个特性及其解决方案。 一、原子性 原子性是指一个操作要么全部完成&#xff0c;要么完全不执行。在多…...

英特尔®以太网网络适配器E810-CQDA1 / E810-CQDA2 网卡 规格书 e810 网卡 规格书 Intel100G E810 网卡 白皮书

英特尔以太网800系列网络适配器 英特尔以太网网络适配器E810-CQDA1 / CQDA2 在10到100Gbps的以太网速度下实现高效的工作负载优化性能 关键特性 •单、双端口QSFP28 •应用设备队列(ADQ) •PCI Express (PCIe) 4.0 x16 •动态设备个性化(DDP) •以太网端口配置工具(EPC…...

好用的idea方法分隔符插件

好用的idea方法分隔符插件...

通过 Xshell 无法连接到 Ubuntu

无法通过 Xshell 连接到 Ubuntu 服务器&#xff0c;通常与 SSH 服务、网络连接、主机防火墙设置问题有关。以下是排查并解决这个问题的步骤&#xff1a; 1. 确保 SSH 服务正在运行 在 Ubuntu 上&#xff0c;SSH 服务必须启动才能连接。如果你有虚拟机或物理机的访问权限&…...

Java面试篇基础部分-Synchronized关键字详解

Synchronized关键字用于对Java对象、方法、代码块等提供线程安全操作。Synchronized属于独占式的悲观锁机制,同时也是可重入锁。我们在使用Synchronized关键字的时候,可以保证同一时刻只有一个线程对该对象进行访问;也就是说它在同一个JVM中是线程安全的。   Java中的每个…...

数据结构之线性表——LeetCode:67. 二进制求和,27. 移除元素,26. 删除有序数组中的重复项

67. 二进制求和 题目描述 67. 二进制求和 给你两个二进制字符串 a 和 b &#xff0c;以二进制字符串的形式返回它们的和。 运行代码&#xff08;javaC) class Solution {public String addBinary(String a, String b) {StringBuilder ansnew StringBuilder();int ca0;for(i…...

SQL_HAVING小例子

例一 求众数的sql语句1&#xff1a; select income,count(*) as cnt from graduates group by income having count(*) > all(select count(*) from graduates group by income);这段SQL语句的作用是从一个名为graduates的表中找出income&#xff08;收入&#xff09;字段…...

Avalonia第三方UI库Semi.Avalonia用法详解

文章目录 简介一、安装Semi Avalonia二、基本项目结构三、使用基本控件1 按钮控件2 输入框控件3 选择框控件四、自定义样式和主题五、使用布局控件六、数据绑定七、事件处理八、使用图标和其他资源九、响应式设计十、交互与导航总结简介 Semi是一个基于Avalonia的UI库,旨在提供…...

宠物智能化听诊器的健康管理!

智能听诊器在宠物健康领域的应用正逐渐普及&#xff0c;它通过创新技术为宠物医疗保健带来革新。以下是智能听诊器如何影响宠物健康管理的概述&#xff1a; 数据分析与机器学习 智能听诊器利用深度学习算法&#xff0c;识别宠物心脏和呼吸模式&#xff0c;提供健康分析和诊断建…...

MyBatis-Plus 实体类注解

MyBatis-Plus 实体类注解详解 MyBatis-Plus 是 MyBatis 的增强版&#xff0c;旨在简化开发者的 CRUD 操作。它通过丰富的特性和注解&#xff0c;简化了数据库与 Java 实体类之间的映射。MyBatis-Plus 提供了一系列的实体类注解&#xff0c;帮助开发者更轻松地映射数据库表、字…...

如何写一个自动化Linux脚本去进行等保测试--引言

#我的师兄喜欢给我的休闲实习生活加活&#xff0c;说是让我在实习期间写一个自动化脚本去进行等保测试。呵呵哒。 怎么办呢&#xff0c;师兄的指令得完成&#xff0c;师兄说让我使用Python完成任务。 设想如下&#xff1a; 1、将Linux指令嵌入到python脚本中 2、调试跑通 …...

美团测开OC!

大家好&#xff0c;我是洋子&#xff0c;最近测试社区里面的一个25届同学参加秋招&#xff0c;已经拿到美团测开offer&#xff0c;今天来分享一下他的求职经历&#xff0c;文末附面经 他求职目前的进展如下&#xff1a; 互联网大厂&#xff1a;字节&#xff0c;阿里&#xff…...

HyperWorks的实体几何创建与六面体网格剖分

创建和编辑实体几何 在 HyperMesh 有限元前处理环境中&#xff0c;有许多操作是针对“实体几何”的&#xff0c;例如创建六面体网格。在创建实体网格的工作中&#xff0c;我们既可以使用闭合曲面创建实体网格&#xff0c;也可以使用完整的实体几何创建实体网格。与闭合曲面相比…...

项目实战:Ingress搭建Nginx+WP论坛+MariaDB

1. 网站架构 本次部署形式完全舍弃 Docker&#xff0c;将所有应用都置于Kubernetes&#xff0c;采用 Deployment 而非单 Pod 部署&#xff0c;稳定性得到升级。 2. 部署 MariaDB [rootk8s-master ~]# mkdir tdr [rootk8s-master ~]# cd tdr/ &#xff08;1&#xff09;定义 …...

UWA支持鸿蒙HarmonyOS NEXT

华为在开发者大会上&#xff0c;宣布了鸿蒙HarmonyOS NEXT将仅支持鸿蒙内核和鸿蒙系统的应用&#xff0c;不再兼容安卓应用&#xff0c;这意味着它将构建一个全新且完全独立的生态系统。 为此&#xff0c;UWA也将在最新版的UWA SDK v2.5.0中支持鸿蒙HarmonyOS NEXT&#xff0c…...

【齐家网-注册/登录安全分析报告】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造成亏损无底洞…...

MyBatis 基本概念

MyBatis 基本概念详解 MyBatis 是一个优秀的持久层框架&#xff0c;它支持定制 SQL、存储过程以及高级映射&#xff0c;用于将 Java 对象与数据库中的记录进行映射。作为 ORM&#xff08;对象关系映射&#xff09;框架&#xff0c;MyBatis 的主要优势在于灵活性高&#xff0c;…...

前端开发之装饰器模式

介绍 装饰器模式 是在不修改对象内部结构的情况下&#xff0c;动态地给对象添加功能的一种设计模式。在软件开发中&#xff0c;有时候我们需要为已有对象添加一些额外的行为&#xff0c;但不希望修改该对象的代码&#xff0c;装饰器模式可以很好的满足这一需求。 在TypeScrip…...

【STL】pair 与 map:基础、操作与应用

C 标准库中提供了许多用于处理数据结构的容器和工具。pair 和 map 是两个非常有用的工具&#xff0c;广泛应用于存储和处理关联数据。在本文中&#xff0c;我们将详细介绍 pair 与 map 的相关操作&#xff0c;并结合代码实例为读者提供清晰的理解。 pair&#xff1a;成对数据的…...

深度学习-图像处理篇4VGG网络

CNN感受野...

效果实测:Image-to-Video如何将风景照变成动态视频?

效果实测&#xff1a;Image-to-Video如何将风景照变成动态视频&#xff1f; 1. 惊艳的开场&#xff1a;静态照片"活"起来了 想象一下&#xff0c;你手机里那些美丽的风景照片突然"活"了过来——海浪开始翻滚&#xff0c;云朵缓缓飘动&#xff0c;树叶在微…...

OpenClaw API配置失败?3步快速修复,免费额度高效利用

OpenClaw API配置失败&#xff1f;3步快速修复&#xff0c;免费额度高效利用引言 OpenClaw作为新一代数据采集平台&#xff0c;其API凭借高效稳定的特性已成为开发者首选的工具之一。但在实际接入过程中&#xff0c;配置失败问题频发&#xff0c;尤其对免费额度用户造成严重困扰…...

Llama-3.2V-11B-cot快速部署:Docker镜像开箱即用,5分钟启动视觉CoT服务

Llama-3.2V-11B-cot快速部署&#xff1a;Docker镜像开箱即用&#xff0c;5分钟启动视觉CoT服务 1. 项目概述 Llama-3.2V-11B-cot是一个支持系统性推理的视觉语言模型&#xff0c;基于LLaVA-CoT论文实现。这个模型能够理解图像内容并进行逐步推理&#xff0c;最终给出合理的结…...

Hackintool:面向黑苹果爱好者的硬件配置诊断与优化工具

Hackintool&#xff1a;面向黑苹果爱好者的硬件配置诊断与优化工具 【免费下载链接】Hackintool The Swiss army knife of vanilla Hackintoshing 项目地址: https://gitcode.com/gh_mirrors/ha/Hackintool 黑苹果配置过程中&#xff0c;硬件兼容性问题常常成为用户最头…...

天问Block环境下ASRPRO语音芯片实战:语音交互、GPIO控制与PWM调光开发指南

1. 天问Block与ASRPRO芯片开发入门 第一次接触天问Block和ASRPRO语音芯片时&#xff0c;我被它们的组合惊艳到了。这个开发环境就像乐高积木一样&#xff0c;通过拖拽代码块就能完成复杂的功能开发&#xff0c;特别适合像我这样的硬件爱好者。ASRPRO作为一款专为语音交互设计的…...

单机变联机:Nucleus Co-Op如何让你的电脑实现4人同屏游戏

单机变联机&#xff1a;Nucleus Co-Op如何让你的电脑实现4人同屏游戏 【免费下载链接】nucleuscoop Starts multiple instances of a game for split-screen multiplayer gaming! 项目地址: https://gitcode.com/gh_mirrors/nu/nucleuscoop 你是否曾想过&#xff0c;用一…...

零成本玩转千问大模型!OpenClaw 配置秘籍(附每日500 Token福利)

&#x1f680;零成本玩转千问大模型&#xff01;OpenClaw 配置秘籍&#xff08;附每日500 Token福利&#xff09; 这份教程将带你完成从环境准备到成功验证的全过程&#xff0c;让你手中的工具“活”起来。 前期准备&#xff1a;搭建基石 在开始代码操作之前&#xff0c;我们需…...

跨平台启动盘制作利器:WinDiskWriter技术解析与应用指南

跨平台启动盘制作利器&#xff1a;WinDiskWriter技术解析与应用指南 【免费下载链接】windiskwriter &#x1f5a5; Windows Bootable USB creator for macOS. &#x1f6e0; Patches Windows 11 to bypass TPM and Secure Boot requirements. &#x1f47e; UEFI & Legacy…...

N_m3u8DL-CLI-SimpleG:让M3U8视频下载变得简单高效的图形化工具

N_m3u8DL-CLI-SimpleG&#xff1a;让M3U8视频下载变得简单高效的图形化工具 【免费下载链接】N_m3u8DL-CLI-SimpleG N_m3u8DL-CLIs simple GUI 项目地址: https://gitcode.com/gh_mirrors/nm3/N_m3u8DL-CLI-SimpleG 在数字内容日益丰富的今天&#xff0c;我们经常遇到需…...

AI五金冲压报价——让精准报价,快人一步。

传统报价熬3天&#xff1f;AI 8分钟给你一份带Excel明细正规PDF的报价单&#xff01;还在用Excel手动算冲压报价&#xff1f;客户催得急&#xff0c;成本核不准&#xff0c;格式不专业丢订单&#xff1f;五金厂的报价痛点&#xff0c;我们懂&#xff01;✅ 工艺PDF/3D图扔进去&…...