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

高薪程序员必修课-java并发编程的bug源头

前言

        Java并发编程虽然强大,但也容易引发复杂的bug。并发编程的bug主要源自以下几个方面:竞态条件、死锁、内存可见性问题和线程饥饿。了解这些bug的源头及其原理,可以帮助开发者避免和解决这些问题。以下是详细的讲解和相应的示例。

1. 竞态条件(Race Condition)

原理

竞态条件发生在多个线程同时访问和修改共享资源时,由于操作的交错顺序不同,导致程序的行为和结果不可预测。具体表现为多个线程在没有适当同步的情况下访问和修改同一变量。

示例

下面是一个竞态条件的示例,演示多个线程同时修改共享变量 counter 的问题。

public class RaceConditionExample {private static int counter = 0;public static void main(String[] args) {Runnable task = () -> {for (int i = 0; i < 1000; i++) {counter++;}};Thread thread1 = new Thread(task);Thread thread2 = new Thread(task);thread1.start();thread2.start();try {thread1.join();thread2.join();} catch (InterruptedException e) {e.printStackTrace();}System.out.println("Final counter value: " + counter);  // 预期结果应为2000}
}

2. 死锁(Deadlock)

原理

死锁是指两个或多个线程相互等待对方持有的资源,导致所有线程都无法继续执行。死锁通常发生在多线程程序中使用多个锁时,锁获取的顺序不一致导致循环等待。

示例

下面是一个简单的死锁示例,两个线程尝试获取相同的锁,但顺序不同,导致死锁。

public class DeadlockExample {private static final Object lock1 = new Object();private static final Object lock2 = new Object();public static void main(String[] args) {Thread thread1 = new Thread(() -> {synchronized (lock1) {System.out.println("Thread 1: Holding lock 1...");try { Thread.sleep(100); } catch (InterruptedException e) {}System.out.println("Thread 1: Waiting for lock 2...");synchronized (lock2) {System.out.println("Thread 1: Holding lock 1 & 2...");}}});Thread thread2 = new Thread(() -> {synchronized (lock2) {System.out.println("Thread 2: Holding lock 2...");try { Thread.sleep(100); } catch (InterruptedException e) {}System.out.println("Thread 2: Waiting for lock 1...");synchronized (lock1) {System.out.println("Thread 2: Holding lock 1 & 2...");}}});thread1.start();thread2.start();}
}

3. 内存可见性问题(Memory Visibility Issues)

原理

内存可见性问题指的是一个线程对共享变量的修改,另一个线程可能看不到。Java内存模型(JMM)允许线程将变量缓存到寄存器或CPU缓存中,而不是立即写入主内存。这会导致不同线程看到的变量值不一致。

示例

下面是一个内存可见性问题的示例,展示了一个线程对变量 running 的修改,另一个线程可能看不到。

public class MemoryVisibilityExample {private static boolean running = true;public static void main(String[] args) {Thread worker = new Thread(() -> {while (running) {// Busy-wait loop}System.out.println("Worker thread stopped.");});worker.start();try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}running = false;System.out.println("Main thread set running to false.");}
}

4. 线程饥饿(Thread Starvation)

原理

线程饥饿发生在某些线程长期得不到执行机会,通常是因为高优先级线程不断占用CPU时间,低优先级线程无法获取CPU资源。导致某些线程长期处于等待状态。

示例

下面是一个线程饥饿的示例,展示了低优先级线程可能永远得不到执行机会。

public class ThreadStarvationExample {public static void main(String[] args) {Thread highPriorityThread = new Thread(() -> {while (true) {// High priority task}});highPriorityThread.setPriority(Thread.MAX_PRIORITY);Thread lowPriorityThread = new Thread(() -> {while (true) {System.out.println("Low priority thread running...");}});lowPriorityThread.setPriority(Thread.MIN_PRIORITY);highPriorityThread.start();lowPriorityThread.start();}
}

总结

竞态条件
  • 原理:多个线程同时访问和修改共享资源。
  • 示例:多个线程同时增加共享变量。
死锁
  • 原理:两个或多个线程相互等待对方持有的资源。
  • 示例:线程1持有锁1等待锁2,线程2持有锁2等待锁1。
内存可见性问题
  • 原理:一个线程对共享变量的修改,另一个线程可能看不到。
  • 示例:一个线程修改变量 running,另一个线程看不到变化。
线程饥饿
  • 原理:某些线程长期得不到执行机会。
  • 示例:高优先级线程不断占用CPU时间,低优先级线程无法获取CPU资源。

理解并发编程中的这些bug源头和原理,并采用适当的同步机制(如 synchronizedLockvolatile)以及并发工具(如 CountDownLatchSemaphoreConcurrentHashMap),可以有效避免和解决这些问题。

相关文章:

高薪程序员必修课-java并发编程的bug源头

前言 Java并发编程虽然强大&#xff0c;但也容易引发复杂的bug。并发编程的bug主要源自以下几个方面&#xff1a;竞态条件、死锁、内存可见性问题和线程饥饿。了解这些bug的源头及其原理&#xff0c;可以帮助开发者避免和解决这些问题。以下是详细的讲解和相应的示例。 1. 竞态…...

c++:#include 某文件.h底层如何寻找其.cpp实现

在C中&#xff0c;当你编写了一个头文件&#xff08;如MyLibrary.h&#xff09;和对应的实现文件&#xff08;如MyLibrary.cpp&#xff09;时&#xff0c;其他源文件&#xff08;如main.cpp&#xff09;只需要包含头文件&#xff08;#include "MyLibrary.h"&#xff…...

uniapp中如何进行微信小程序的分包

思路&#xff1a;在uniapp中对微信小程序进行分包&#xff0c;和原生微信小程序进行分包的操作基本上没区别&#xff0c;主要就是在pages.json中进行配置。 如图&#xff0c;我新增了一个包diver-page 此时需要在pages.json中的subPackages数组中新增一项 root代表这个包的根…...

win10下安装PLSQL14连接Oracle数据库

问题背景 在使用Oracle开发过程中&#xff0c;经常会使用工具来连接数据库&#xff0c;方便查询、处理数据。其中有很多工具可以使用&#xff0c;比如dbeaver、plsql等。本文主要介绍在win10环境下&#xff0c;plsql14的安装步骤以及安装过程中遇到的一些问题。 安装步骤及问题…...

高考失利咨询复读,银河补习班客服开挂回复

补习班的客服在高考成绩出来后&#xff0c;需要用专业的知识和足够的耐心来回复各种咨询&#xff0c;聊天宝快捷回复软件&#xff0c;帮助客服开挂回复。 ​ 前言 高考成绩出来&#xff0c;几家欢喜几家愁&#xff0c;对于高考失利的学生和家长&#xff0c;找一个靠谱的复读补…...

java 代码块

Java中的代码块主要有三种类型&#xff1a;普通代码块、静态代码块、构造代码块。它们的用途和执行时机各不相同。 普通代码块&#xff1a;在方法内部定义&#xff0c;使用一对大括号{}包围的代码片段。它的作用域限定在大括号内&#xff0c;每当程序执行到该代码块时就会执行其…...

vue中避免多次请求字典接口

vuex缓存所有字典项 背景vuex管理所有字典项调用字典接口处理字典项数据的filter页面中使用字典 背景 每次用到字典都需要通过对应的字典type调用一次字典接口&#xff0c;当一个页面用到字典项很多时&#xff0c;接口请求炒鸡多&#xff0c;会导致接口响应超时。 本篇文章改为…...

Snappy使用

Snappy使用 Snappy是谷歌开源的压缩和解压的开发包&#xff0c;目标在于实现高速的压缩而不是最大的压缩 项目地址&#xff1a;GitHub - google/snappy&#xff1a;快速压缩器/解压缩器 Cmake版本升级 该项目需要比较新的cmake&#xff0c;CMake 3.16.3 or higher is requi…...

跨越重洋:在Heroku上配置Pip镜像源的终极指南

&#x1f310; 跨越重洋&#xff1a;在Heroku上配置Pip镜像源的终极指南 Heroku是一个支持多种编程语言的云平台即服务&#xff08;PaaS&#xff09;&#xff0c;它允许开发者部署和管理应用程序。然而&#xff0c;由于Heroku的服务器位于海外&#xff0c;直接使用Python的包管…...

SpringBoot + 虚拟线程,性能炸裂!

一、什么是虚拟线程 虚拟线程是Java19开始增加的一个特性&#xff0c;和Golang的携程类似&#xff0c;一个其它语言早就提供的、且如此实用且好用的功能&#xff0c;作为一个Java开发者&#xff0c;早就已经望眼欲穿了。 二、虚拟线程和普通线程的区别 “虚拟”线程&#xf…...

Java Character类

Character是char的包装类 转义序列 Character类的方法...

Python中的爬虫实战:猫眼电影爬虫

随着互联网技术的快速发展&#xff0c;网络上的信息量越来越庞大。猫眼电影作为国内领先的电影数据平台&#xff0c;为用户提供了全面的电影信息服务。本文将介绍如何利用python编写简单的猫眼电影爬虫&#xff0c;获取电影相关数据。 爬虫概述 爬虫&#xff0c;即网络爬虫&a…...

WAIC2024 | 华院计算邀您共赴2024年世界人工智能大会,见证未来科技革新

在智能时代的浪潮汹涌澎湃之际&#xff0c;算法已成为推动社会进步的核心力量。作为中国认知智能技术的领军企业&#xff0c;华院计算在人工智能的广阔天地中&#xff0c;不断探索、创新&#xff0c;致力于将算法的潜力发挥到极致。在过去的时日里&#xff0c;华院计算不断探索…...

数据库原理之数据库基本概念

目录 前言 基本概念 数据库完整性 前言 今天我们来看看数据库的基本概念&#xff0c;帮助大家对数据库有一点点最基本的了解 基本概念 4个基本概念 数据data&#xff1a;描述事物的符号&#xff0c;数据库中存储的基本对象。 数据库Database&#xff1a;长期存储在计算机…...

vue2项目的打包以及部署

打包 当我们写好vue2的项目后&#xff0c;可以通过npm build来对项目进行打包 npm build 打包完成后我们可以看到在当面目录下生成了dis目录,src下的文件都会被打包进这个目录里&#xff0c;当然打包后的文件我们不能直接在浏览器打开&#xff0c;需要进行部署 部署 1.新建一个…...

Java的全局异常处理代码

第一步&#xff1a;先写一个异常管理类: package com.example.firefighting.exceptions;import com.example.firefighting.utils.Result; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerA…...

Hi3861 OpenHarmony嵌入式应用入门--LiteOS semaphore作为锁

CMSIS 2.0 接口中的 Semaphore&#xff08;信号量&#xff09;是用于嵌入式系统中多线程或中断服务例程&#xff08;ISR&#xff09;之间同步和共享资源保护的重要机制。Semaphore 是一种用于控制对多个共享资源访问的同步机制。它可以被看作是一个计数器&#xff0c;用于跟踪可…...

注意!年龄越大,社交圈子越窄?其实这是老人的理性选择!数学家告诉你:何时该跳槽,何时该坚守!你必须知道的三个智慧:让你的人生更加精彩!

我们到底应该在什么情况下探索新事物&#xff0c;什么情况下专注于已有的东西呢&#xff1f;本质上来说&#xff0c;这个问题就是在询问&#xff0c;你究竟应该耗费精力去探索新的信息&#xff0c;还是专注从既有的信息中获取收获&#xff1f; 有人采访了临终的老人&#xff0c…...

[SwiftUI 开发] 嵌套的ObservedObject中的更改不会更新UI

1. 发生问题的demo 业务逻辑代码 class Address: ObservableObject {Published var street "123 Apple Street"Published var city "Cupertino" }class User: ObservableObject {Published var name "Tim Cook"Published var address Addr…...

全面了解机器学习

目录 一、基本认识 1. 介绍 2. 机器学习位置 二、机器学习的类型 1. 监督学习 2. 无监督学习 3. 强化学习 三、机器学习术语 1. 训练样本 2. 训练 3. 特征 4. 目标 5. 损失函数 四、机器学习流程 五、机器学习算法 1. 分类算法 2. 聚类算法 3. 关联分析 4. …...

.Net框架,除了EF还有很多很多......

文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

全球首个30米分辨率湿地数据集(2000—2022)

数据简介 今天我们分享的数据是全球30米分辨率湿地数据集&#xff0c;包含8种湿地亚类&#xff0c;该数据以0.5X0.5的瓦片存储&#xff0c;我们整理了所有属于中国的瓦片名称与其对应省份&#xff0c;方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...

Mac软件卸载指南,简单易懂!

刚和Adobe分手&#xff0c;它却总在Library里给你写"回忆录"&#xff1f;卸载的Final Cut Pro像电子幽灵般阴魂不散&#xff1f;总是会有残留文件&#xff0c;别慌&#xff01;这份Mac软件卸载指南&#xff0c;将用最硬核的方式教你"数字分手术"&#xff0…...

【C语言练习】080. 使用C语言实现简单的数据库操作

080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...

聊一聊接口测试的意义有哪些?

目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开&#xff0c;首…...

3-11单元格区域边界定位(End属性)学习笔记

返回一个Range 对象&#xff0c;只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意&#xff1a;它移动的位置必须是相连的有内容的单元格…...

dify打造数据可视化图表

一、概述 在日常工作和学习中&#xff0c;我们经常需要和数据打交道。无论是分析报告、项目展示&#xff0c;还是简单的数据洞察&#xff0c;一个清晰直观的图表&#xff0c;往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server&#xff0c;由蚂蚁集团 AntV 团队…...

C++.OpenGL (14/64)多光源(Multiple Lights)

多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...

Java + Spring Boot + Mybatis 实现批量插入

在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法&#xff1a;使用 MyBatis 的 <foreach> 标签和批处理模式&#xff08;ExecutorType.BATCH&#xff09;。 方法一&#xff1a;使用 XML 的 <foreach> 标签&#xff…...

[ACTF2020 新生赛]Include 1(php://filter伪协议)

题目 做法 启动靶机&#xff0c;点进去 点进去 查看URL&#xff0c;有 ?fileflag.php说明存在文件包含&#xff0c;原理是php://filter 协议 当它与包含函数结合时&#xff0c;php://filter流会被当作php文件执行。 用php://filter加编码&#xff0c;能让PHP把文件内容…...