《java并发编程的艺术》读书笔记 1~2章

2023-09-14 19:35:15

1.java并发基本概念

1.1上下文切换

实现原理:通过CPU时间片来实现这个机制。时间片是CPU分配给各个线程的时间,时间片非常短,CPU通过不停的切换线程执行,让我们感觉多个线程是同时执行的。

CPU通过时间片分配算法来循环执行任务,当前任务执行一个时间片会切换到下一个任务,并保存上一个任务的状态,下次切换到这个任务时就会加载这个状态,这就是一次上下文切换。

上下文切换会影响多线程执行速度的。

上下文切换和线程创建在某些时候甚至会导致并发比串行慢。

1.1.1减少上下文切换

减少上下文切换的方法有无锁并发编程、CAS算法、使用最少线程和使用协程等。

无锁并发编程:多线程竞争锁时,会引起上下文切换,所以多线程处理数据时,可以用一些
办法来避免使用锁,如将数据的ID按照Hash算法取模分段,不同的线程处理不同段的数据。

CAS算法:CAS算法通过比较内存中的值与预期值是否相等来判断内存中的值是否被其他线程修改过,并在相等的情况下将新值写入内存。Java的Atomic包使用CAS算法来更新数据,而不需要加锁。

协程:在单线程里实现多任务的调度,并在单线程里维持多个任务间的切换。

1.2 死锁

当两个线程互相等待对方获得锁的时候就会造成死锁。

一般来说,是因为没有正常释放锁造成的。

避免死锁的方法:

避免一个线程同时获取多个锁,避免一个线程在锁内同时占用多个资源,使用定时锁。

2.Java并发机制的底层实现原理

2.1 volatile的应用

volatile保证了共享变量的“可见性”。volatile变量修饰符使用恰当的话,它比synchronized的使用和执行成本更低,因为它不会引起线程上下文的切换和调度。

2.1.1volatile的实现原理

通过Lock前缀的指令,将当前处理器缓存行的数据写回到系统内存。使在其他CPU里缓存了该内存地址的数据无效。

每个处理器通过嗅探在总线上传播的数据来检查自己缓存的值是不是过期了

2.2 synchronized的实现原理与应用

Java中的每一个对象都可以作为锁。具体表现为以下3种形式。
·对于普通同步方法,锁是当前实例对象。
·对于静态同步方法,锁是当前类的Class对象。
·对于同步方法块,锁是Synchonized括号里配置的对象。

锁一共有4种状态,从低到高是无锁状态、偏向锁状态、轻量级锁状态和重量级锁状态。

锁可以升级但不能降级。

1.偏向锁

偏向锁使用了一种等到竞争出现才释放锁的机制,所以当其他线程尝试竞争偏向锁时,持有偏向锁的线程才会释放锁。加锁和解锁不会有额外的性能消耗,适用于只有一个线程访问同步块的场景,如果线程之间存在竞争会导致额外的锁撤销的消耗。

2.轻量级锁

竞争的线程不会阻塞,会通过自旋来尝试获取锁。缺点是一直没有得到锁的线程持续自旋会导致CPU消耗,适用于追求响应速度的场景

3.重量级锁

线程竞争通过阻塞实现,响应速度慢,适用于追求吞吐量的环境,同步块执行速度慢。

2.3原子操作的实现原理

处理器一般使用总线锁定和缓存锁定两个机制来保证复杂内存操作的原子性。

2.3.1.总线锁

当一个处理器在总线上输出此信号时,其他处理器的请求将被阻塞住,那么该处理器可
以独占共享内存。

2.2.2.缓存锁

当一个处理器要修改一个经常被其他处理器读取的内存地址时,它可以向所有其他处理器发送一个请求,在请求期间,其他处理器会将与该地址相关的缓存行设置为无效状态,即将其从缓存中移除。这就是缓存锁定的过程,也被称为缓存锁定操作。在这个过程中,其他处理器无法读取或修改与该地址相关的数据,直到缓存锁定操作完成。

2.3.3.java如何实现原子操作
1.使用循环CAS实现原子操作

自旋CAS实现的基本思路就是循环进行CAS操作直到成功为止。

CAS实现原子操作的三大问题

ABA问题,循环时间长开销大,以及只能保证一个共享变量的原子操作。

1.ABA问题解决方案:通过版本号来解决,在变量前面追加上版本号,每次变量更新的时候把版本号加1。

2.循环时间开销问题:延迟自旋的速度来减少CPU的消耗。

3.只能保证一个变量原子性,可以通过多个共享变量合并成一个变量来操作。

2.使用锁机制实现原子性

JVM内部实现了很多种锁机制,有偏向锁、轻量级锁和互斥锁。有意思的是除了偏向锁,JVM实现锁的方式都用了循环CAS,即当一个线程想进入同步块的时候使用循环CAS的方式来获取锁,当它退出同步块的时候使用循环CAS释放锁。

更多推荐

访问者模式简介

概念:访问者模式(Visitorpattern)是一种行为型设计模式,它允许在不修改已有对象结构的情况下定义新操作。该模式将数据结构与操作分离,使得新增操作变得容易,并且可以在不同的数据结构上复用相同的操作。特点:将操作封装到独立的访问者类中,使得添加新的操作变得简单。可以对一个对象结构中的元素进行多种不同类型的遍历和

Remix 和 Next.js 中实现依赖注入

文章目录在Remix中实现依赖注入在Next.js中实现依赖注入对比小结在Remix中实现依赖注入在Remix中实现依赖注入需要使用到context。下面是一个简单的示例:首先,在项目根目录下创建context.js文件:importReactfrom'react';constDependenciesContext=R

【Spatial-Temporal Action Localization(二)】论文阅读2017年

文章目录1.ActionVLAD:Learningspatio-temporalaggregationforactionclassification[code](https://github.com/rohitgirdhar/ActionVLAD/)[](https://github.com/rohitgirdhar/

platform驱动模型

一、总线驱动模型1.概念linux中将一个挂载在总线上的驱动的驱动模型分为三部分:device、driver和bus。device是用来保存设备信息的对象,存放在内核中一个klist_device链表中进行管理。driver当前设备的驱动信息对象,存放在内核中一个klist_driver链表中进行管理。bus是当前设备

【Python从入门到进阶】36、Selenium 动作交互

接上篇《35、selenium基本语法学习》上一篇我们介绍了selenium的基本语法,包括元素定位以及访问元素信息的操作。本篇我们来学习selenium操作网页的动作内容。一、什么是selenium动作操作动作操作是指使用Selenium调用WebDriver执行与用户交互相关的动作,例如单击、右键单击、悬停、拖放等

Redis集群搭建

Redis集群搭建1、主从模式部署1.1环境准备IP主机名角色192.168.54.200mastermaster192.168.54.201slave1slave1192.168.54.202slave2slave21.2下载下载地址:http://download.redis.io/releases/这里选择下载:

全链路自动化测试

背景从SOA架构到现在大行其道的微服务架构,系统越拆越小,整体架构的复杂度也是直线上升,我们一直老生常谈的微服务架构下的技术难点及解决方案也日渐成熟(包括典型的数据一致性,系统调用带来的一致性问题,还是跨节点跨机房复制带来的一致性问题都有了很多解决方案),但是有一个环节我们明显忽略了。在现在的微服务架构趋势下,微服务在

微信小程序| 打造ChatGPT英语四六级背单词小程序

一、需求背景学英语,最大的痛苦莫过于背单词!不知道你平时都是用什么方式在背单词呢?硬啃单词书?字典?还是说各类的背单词APP来回跳转?不可否认的是,单词一两遍完全记不住,没有个三四五六七八遍,都很难在考场的卷子上认出他!所以,这次我们来做一个通关英语四六级的背单词神器,让他能够基于艾宾浩斯遗忘规律来辅助我们高效背单词。

数仓主题域和数据域、雪花模型,星型模型和星座模型

数仓模型和领域划分一、主题域和数据域的差别二、雪花模型,星座模型和星型模型一、主题域和数据域的差别明确数据域作为数仓搭建的重要一环,能够让数仓的数据便于管理和应用。数据域和主题域都是数据仓库中的重要概念,但含义略有不同,常常作为面试官的面试考点。数据域指的是特定的业务领域或是业务过程,如销售、采购、人力资源管理、财务等

前端需要知道的计算机网络知识----网络安全,自学网络安全,学习路线图必不可少,【282G】初级网络安全学习资源分享!

网络安全(英语:networksecurity)包含网络设备安全、网络信息安全、网络软件安全。黑客通过基于网络的入侵来达到窃取敏感信息的目的,也有人以基于网络的攻击见长,被人收买通过网络来攻击商业竞争对手企业,造成网络企业无法正常营运,网络安全就是为了防范这种信息盗窃和商业竞争攻击所采取的措施。随着互联网的高速发展,信

如何写一份出色的毕业设计任务书

title:如何写一份出色的毕业设计任务书date:2023-09-20毕业设计任务书是每个毕业生必须面对的关键文档。它不仅是你完成毕业设计的路线图,还是导师评估你工作的依据。因此,撰写一份清晰、详细且具体的任务书至关重要。本文将向你介绍如何编写一份出色的毕业设计任务书。1.确定项目背景和目的任务书的第一部分应该解释你

热文推荐