《Java并发编程实战》学习笔记(1)

ESP32-S3数字麦克风入门:手把手教你用Arduino IDE读取MSM261S4030H0R的I2S数据 本文详细介绍了如何使用Arduino IDE读取MSM261S4030H0R数字麦克风的I2S数据,涵盖硬件连接、代码编写和数据可视化全流程。重点解决I2S引脚配置、环境噪声过滤和声波观察等实际问题,适合ESP32-S3开发者快速上手数字麦克风应用。 阅读详情

第一章:介绍

知识点:

  • 进程是资源(CPU、内存等)分配的基本单位
  • 线程是CPU调度和分派的基本单位
  • 一个进程包括一个或多个线程

1、为什么应用程序需要从单线程发展为多线程(从同步到异步)?

  • 资源利用。程序有时候需要等待外部的操作,比如输入和输出,并且在等待的时候不可能进行有价值的工作。在等待的时候,让其他的程序运行会提高效率。
  • 公平。多个用户或程序可能对系统资源有平等的优先级别。让他们通过更好的时间片方式来共享计算机,这要比结束一个程序后才开始下一个程序更可取。
  • 方便。写一些程序,让它们各自执行一个单独任务并进行必要的相互协调,这要比编写一个程序来执行所有的任务更容易,更让人满意。

第二章:线程安全

一个对象的状态就是它的数据。编写线程安全的代码,本质上就是管理对状态(state)的访问,而且通常都是共享的、可变的状态。

所谓共享,是指一个变量可以被多个线程访问;所谓可变,是指变量的值在其生命周期内可以改变。我们讨论的线程安全性好像是关于代码的,但是我们真正要做的,是在不可控制的并发访问中保护数据。

在没有正确同步的情况下,如果多个线程访问了同一个变量,你的程序就存在隐患。有3种方法修复它:

  • 不要跨线程共享变量;
  • 使状态变量为不可变的;或者
  • 在任何访问状态变量的时候使用同步。

线程安全的定义:

当多个线程访问一个类时,如果不用考虑这些线程在运行时环境下的调度和交替执行,并且不需要额外的同步及在调用方代码不必作其他的协调,这个类的行为仍然是正确的,那么称这个类是线程安全的。

无状态对象永远是线程安全的。

线程不安全之复合操作

读-改-写(read-modify-write)

@NotThreadSafe
public class UnsafeCountingFactorizer implements Servlet {
    private long count = 0;
    public long getCount() { return count; }
    public void service(ServletRequest req, ServletResponse resp) {
        BigInteger i = extractFromRequest(req);
        BigInteger[] factors = factor(i);
        ++count;
        encodeIntoResponse(resp, factors);
    }
}

检查再运行(check-act)

@NotThreadsafe
public class LazyInitRace {
    private Expensive0bject instance = null;
    public ExpensiveObject getInstance() {
        if ( instance == null ) {
            instance = new Expensive0bject();
        }
        return instance;
    }
}

为了确保线程安全,“检查再运行” 操作(如惰性初始化)和读-改-写操作(如自增)必须是原子操作。我们将“检查再运行”和“读-改-写”的全部执行过程看作是复合操作:为了保证线程安全,操作必须原子地执行。

我们会在下一节考虑用Java内置的原子性机制——锁。现在,我们先用其他方法修复这个问题——使用已有的线程安全类。

@ThreadSafe
public class CountingFactorizer implements Servlet {
    private final AtomicLong count = new AtomicLong(0);
    public long getCount() { return count.get(); }
    public void service(ServletRequest req, ServletResponse resp) {
        BigInteger i = extractFromRequest(req);
        BigInteger[] factors = factor(i);
        count.incrementAndGet();
        encodeIntoResponse(resp, factors);
    }
}

java.util.concurrent.atomic包中包括了原子变量(atomic variable) 类,这些类用来实现数字和对象引用的原子状态转换。把long类型的计数器替换为AtomicLong类型的,我们可以确保所有访问计数器状态的操作都是原子的。计数器是线程安全的了。

内部锁

Java提供了强制原子性的内置锁机制:synchronized。一个synchronized块有两部分:锁对象的引用,以及这个锁保护的代码块。

每个Java对象都可以隐式地扮演一个用于同步的锁的角色;这些内置的锁被称作内部锁(intrinsic locks)或监视器锁(monitor locks)。

执行线程进入synchronized块之前会自动获得锁;而无论通过正常控制路径退出,还是从块中抛出异常,线程都在放弃对synchronized块的控制时自动释放锁。

获得内部锁的唯一途径是:进入这个内部锁保护的同步块或方法。

内部锁在Java中扮演了互斥锁(mutual exclusion lock,也称作mutex)的角色,意味着至多只有一个线程可以拥有锁,当线程A尝试请求一个被线程B占有的锁时,线程A必须等待或者阻塞,直到B释放它。如果B永远不释放锁,A将永远等下去。

重进入(Reentrancy)

当一个线程请求其他线程已经占有的锁时,请求线程将被阻塞。然而内部锁是可重进入的,因此线程在试图获得它自己占有的锁时,请求会成功。

重进入意味着所的请求是基于“每线程(per-thread)”,而不是基于“每调用(per-invocation) ”的。

重进入的实现是通过为每个锁关联一个请求计数(acquisition count)和一个占有它的线程。当计数为0时,认为锁是未被占有的。

线程请求一个未被占有的锁时,JVM将记录锁的占有者,并且将请求计数置为1。如果同一线程再次请求这个锁,计数将递增;每次占用线程退出同步块,计数器值将递减。直到计数器达到0时,锁被释放。

/**
*	如果该锁不是可重入的,代码将死锁
*/
public class Widget {
	public synchronized void doSomething() {
		...
	}
}
public class LoggingWidget extends Widget {
	@Override
	public synchronized void doSomething() {
		super.doSomething();
	}
}

对于每个可被多个线程访问的可变状态变量,如果所有访问它的线程在执行时都占有同一个锁,这种情况下,我们称这个变量是由这个锁保护的。

每个共享的可变变量都需要由唯一一个确定的锁保护。

适当调整synchronized块的大小,使其在安全和性能之间达到平衡。

有些耗时的计算或操作,比如网络或控制台I/O,难以快速完成。执行这些操作期间不要占有锁。

AIDC智算中心建设:资源池化核心技术解析 AI 应用的POD在运行的时候,通过池化运行时访问虚拟GPU、执行AI任务,池化运行时拦截对虚拟GPU的访问请求、转递给池化服务代理执行,池化服务代理通过向智算池化控制器查询虚拟GPU所对应的真实智算资源位置、规格,按查询结果分配智算资源、执行AI任务,如果真实的智算资源位于远程计算节点,则由本地池化服务代理将访问请求转递给远程计算节点上的池化服务代理处理,相关通信经由参数面网络。 阅读详情

相关推荐

多元相关性分析_PAST:最简便易用的统计学分析软件教程目录

欢迎来到PAST的世界!本教程并不是将PAST的所有功能均进行详细介绍,而只是挑选与生物、医学、微生物研究相关的统计学分析内容进行讲述。根据PAST内各项分析的标签分类,将该教程具体设置如下:PAST软件介绍PAST的基本信息数据的输入和修改数据的转换和标准化图像绘制 (Plot标签)点线图和直方图散点图条形图和箱须图饼图堆叠条形图三元相图气泡图单变量统计学分析 (Univariate标...

weixin_39605706的博客 3155

Spring AOP 解决前后端恶意刷新页面和API接口服务

Spring AOP 解决前后端恶意刷新页面和API接口服务,为了避免恶意接口请求和页面刷新。对于每个IP单位时间内次数限制,这些被认定为恶意请求,将对应访问的时间戳和次数写入Redis进行自动过期处理。 目录 对单个接口方法 定义@LimitMethod注解 定义LimitReqHandler计数器 定义LimitMethodReqAspect切面组件 使用@LimitMetho...

纸上得来终觉浅,绝知此事要躬行 995

国产麒麟系统下用Rider开发C#桌面应用:从环境配置到Avalonia UI实战

本文详细介绍了在国产麒麟系统上使用JetBrains Rider开发C#桌面应用的完整流程,重点讲解了Avalonia UI框架的实战应用。从环境配置、Rider安装到Avalonia项目创建和UI开发技巧,全面覆盖了在非Windows环境下进行C#开发的关键步骤和优化建议,助力开发者高效构建跨平台桌面应用。

weixin_27791839的博客 387

OkHttp相关问题全解析

先来一发灵魂拷问四连击: addInterceptor与addNetworkInterceptor有什么区别? 网络缓存如何实现的? 网络连接怎么实现复用? OkHttp如何做网络监控? 是不是既熟悉又陌生,实际上就是因为网络框架已经为我们实现了这些基本功能,所以很容易被我们忽略。为了完整的分析上面的问题,我们需要先复习一下OkHttp的基础原理: OkHttp基本实现原理 OkHttp的内部实现通过一个责任链模式完成,将网络请求的各个阶段封装到各个链条中,实现了各层的解耦。 文内源码基于Ok

augfun的博客 1718

手把手教你读懂蓝牙BQB射频测试报告:以PRBS9为例的实战分析

本文以蓝牙BQB射频测试中的PRBS9信号为例,提供了一份实战分析指南。文章深入解读了输出功率、调制特性、邻道泄漏等核心测试项,并分享了信号分析仪操作技巧、测试环境搭建要点及设备选型建议,旨在帮助工程师精准解读报告,高效定位问题,确保产品顺利通过认证。

weixin_29289821的博客 260

LTR-390UV-01对比VEML6075:5个真实项目中的选型避坑指南

本文对比了LTR-390UV-01和VEML6075两款环境光传感器在5个真实项目中的表现,提供了选型避坑指南。通过智能手环、农业温室、紫外线消毒柜等场景的实测数据,分析了动态范围、抗干扰性、温度稳定性等关键差异,帮助开发者在成本与性能间做出最优选择。

weixin_28733777的博客 219

leetcode并发题目解题报告JAVA版

一、Print in Order Suppose we have a class: public class Foo { public void first() { print("first"); } public void second() { print("second"); } public void third() { print("third"); } } T...

松花皮蛋的黑板报 275

蓝牙攻防实战:蓝牙技术详解

蓝牙作为轻量级、低功耗的无线通信技术,其设计兼顾了效率与灵活性,但也留下了诸多安全隐患。随着物联网设备的爆发式增长,蓝牙的攻击面也在不断扩大。理解其底层通信机制、协议栈结构以及配对加密逻辑,是提升无线安全防护能力的关键。

idlecloud0105的博客 739

check then act and read modify write

翻译自stackoverflow: 问题: 例1:check then act if(vector.contains(e))//check { vector.remove(e) } f there are 2 threads can access, thread1 suspends after check vector contains e, and e does in vecto

north hunter 1512

【深度学习】Progressive Distillation for Fast Sampling of Diffusion Models

这种方法通过迭代地将一个需要较多步骤的模型(称为教师模型)蒸馏成一个需要较少步骤的学生模型,每次迭代都将采样步骤减半,直到达到所需的采样步骤数量。通过渐进式蒸馏,论文将原始需要8192步采样的模型成功蒸馏为只需4步采样就能取得接近的生成质量的新模型,大幅提高了扩散模型的推理效率。这篇论文提出了一种"渐进式蒸馏"(Progressive Distillation)的方法,来大幅降低用于生成对抗网络(GAN)的扩散模型(Diffusion Model)在推理阶段的采样步数,从而提高其推理效率。

q742971636的博客 1785

汇川H5U PLC 实现直线插补、圆弧插补、直线圆弧混合连续插补

使用汇川H5UPLC实现直线插补,圆弧插补,直线圆弧混合路径插补,通过示教可以走出复杂的路径,仅供参考学习。

weixin_39832501的博客 4773

线程不安全类 示例(三)先检查再执行

先检查再执行 就算a是原子性的,但在if和进入if块之间,别的线程是有可能插进来的; if(condition(a) { handle(a); }

乌鲁木齐001号程序员 158

PCL 使用点云创建数字高程模型DEM【2025最新版】

使用点云创建数字高程模型DEM,并将结果保存为高程图像。博客长期更新,本文最近更新时间为:2025年9月15日。

点云侠的博客 2294

《Java并发编程实战》学习笔记(1)

又挖了一个待更新的坑。。。 书籍链接 学习的是2012版的《Java并发编程实战》,找了半天网上只有不带书签的pdf版,而优快云下载也因为版权问题不允许上传和下载这本书,于是自己用acrobat给这本书添加了书签,在这里放上百度云链接,有需自取,链接无效可以评论邮件发。 链接:https://pan.baidu.com/s/16Y56Yej5LvbSMRMhVfu...

TQY724的博客 360

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

Java学习推荐书籍

看书是每个Javaer必修课,在看过视频后还需要书来辅助查漏补缺,这里我给大家推荐基本书,基本可以涵盖从起步到就业后期提升啦。 第一本:起步图书《Head First Java》 这本书特别适合讨厌读书的同胞们,如果阅读这本书,一定会让你觉得很有趣。通过这样一本通俗易懂的教科书,既能学习知识,又能收获快乐;非常适合作为入门图书来学习。但是需要注意的是千万不要讲本书当做段子书来看。 第二本:入门图书《Java学习笔记》 Java学习笔记收录了作者多年来的学习及教学经验,作者将Java相关的概念、操作以及应用以

m0_56691207的博客 213

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

《Java 并发编程实战》学习笔记一

多核时代每颗 CPU 都有自己的缓存,这时 CPU 缓存(三级缓存)与内存的数据一致性就容易出现问题了,当多个线程在不同的 CPU 上执行时,这些线程操作的是不同的 CPU 缓存。比如,线程 A 操作的是 CPU-1 上的缓存,而线程 B 操作的是 CPU-2 上的缓存,很明显,这个时候线程 A 对变量 V 的操作对于线程 B 而言就不具备可见性了。:高级语言里一条语句往往需要多条 CPU 指令完成,例如count += 1这句代码,至少需要三条 CPU 指令。

yibushao的博客 1152

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

【极客时间】《Java并发编程实战》学习笔记

【极客时间】《Java并发编程实战》学习笔记

Mr.Cui的Java学习之路 2648

Java并发编程实战(1)

该系列文章是博主学习笔记,禁止转载,读书交流群:946541246 · 文章目录Java并发编程实战一二章学习概念无状态竟态条件不变性条件相互约束的变量要在一个原子操作中进行复合操作 Java并发编程实战一二章学习 概念 无状态 既不包含任何域,也不包含任何对其他类中域的引用。 无状态一定是线程安全的 例如 @ThreadSafe public class StatelessFactorizer...

谢耀眼 467

Java并发编程实战总结

Java并发编程

qq_39817635的博客 1547

《JAVA并发编程的艺术》之 Java并发编程实战

《JAVA并发编程的艺术》之 Java并发编程实战 文章目录《JAVA并发编程的艺术》之 Java并发编程实战生产者和消费者模式生产者消费者模式实战多生产者和多消费者场景线程池与生产消费者模式线上问题定位性能测试查看网络流量。查看系统平均负载。查看系统内存情况。查看CPU的利用率。异步任务池 当你在进行并发编程时,看着程序的执行速度在自己的优化下运行得越来越快,你会觉得越来越有成就感,这就是并发编程的魅力。但与此同时,并发编程产生的问题和风险可能也 会随之而来。本章先介绍几个并发编程的实战案例,然后再介绍如

weixin_44019182的博客 1319

【Java并发编程实战】

本篇是阅读《Java 并发编程实战》的零碎笔记,整体非常凌乱,并不适合阅读,仅做个人备忘。

猫吻鱼的博客 1473

Java 并发编程的艺术

内容简介 书中采用循序渐进的讲解方式,从并发编程的底层实现机制入手,逐步介绍了在设计 Java 并发程序时各种重要的技术、设计模式与应用,同时辅以丰富的示例代码,使得开发人员能够更快地领悟 Java 并发编程的要领,围绕着 Java 平台的基础并发功能快速地构建大规模的并发应用程序。 第1章介绍 Java 并发编程的挑战,会向读者说明可能会遇到哪些问题,以及如何解决。 第2章 Java 并发编程...

GitChat 2691

Java并发编程实战(2)

该系列文章是博主学习笔记,禁止转载,读书交流群:946541246 文章目录Java并发编程实战三四章学习加锁与可见性volatile Java并发编程实战三四章学习 加锁与可见性 锁可以用于确保某个线程以一种可预测的方式来查看另一个线程的执行结果 当线程A执行某个同步代码时,线程B随后进入由同一个锁保护的同步代码块,在这种情况下可以保证,在锁被释放钱,A看到的变量值在B获得锁后同样可以由B看到。...

谢耀眼 1008

Java并发编程:深入探索与实战案例

Java并发编程是一个复杂而强大的领域,它提供了多种工具和技术来应对多线程环境下的挑战。从基础的到高级的 ` LockAtomic `类,再到线程池和并发集合,Java为开发者提供了丰富的选择。通过理解这些工具的工作原理,并结合实际场景进行应用,我们可以构建出高性能、可扩展的并发应用程序。本文介绍的实战案例,展示了如何将这些知识应用于构建一个简单但高效的Web服务器,希望对读者有所启发。

运维人生 1461

Java并发编程实战 Day 1:Java并发编程基础与线程模型

欢迎来到为期30天的《Java并发编程实战》系列教程。本系列将从Java并发编程的基础知识讲起,逐步深入到高级特性与实战应用,帮助开发者构建高性能、可扩展的并发系统。作为开篇第一天,我们将聚焦于Java并发编程基础与线程模型,重点包括以下内容:通过今天的学习,您将掌握如何在Java中高效地管理多线程任务,并为后续更复杂的并发编程打下坚实基础。线程是操作系统调度的最小单元,一个进程中可以包含多个线程,每个线程都有独立的执行路径。Java语言内置了对多线程的支持,使得开发者可以轻松实现并发程序。| 特性 | 进

在未来等你的专栏 1048

【免费下载】 Java 并发编程实战高清PDF版

Java 并发编程实战高清PDF版 【下载地址】Java并发编程实战高清PDF版 本仓库提供了一份名为《Java 并发编程实战高清PDF版》的资源文件,该文件深入讲解了Java并发编程技术,涵盖了多线程、锁机制以及Java内存模型等关键内容 ...

gitblog_09761的博客 2295
上一篇: 【Oracle】根据条件更新多个字段的值
下一篇: 《Java并发编程实战》学习笔记(2)
章 鱼
博客等级 码龄10年 203粉丝 105原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值