《Java并发编程的艺术》知识点

2023-11-17

目录

一 并发编程挑战

1.上下文切换

含义:
    CPU通过时间片分配算法来循环执行任务,当前任务执行一个时间片后会切换到下一个任务。但是,在切换前会保存上一个任务的状态,以便下次切换回这个任务时,可以再加载这个任务的状态。所以任务从保存到再加载的过程就是一次上下文切换。

如何减少上下文切换:
    1)无锁并发
    2)CAS
    3)使用最少线程
    4)协程:在单线程里实现多任务的调度,并在单线程里维持多个任务间的切换

2.死锁

避免死锁方法:
    1)避免一个线程同时获取多个锁。
    2)避免一个线程在锁内同时占用多个资源,尽量保证每个锁只占用一个资源。
    3)尝试使用定时锁,使用lock.tryLock(timeout)来替代使用内部锁机制。
    4)对于数据库锁,加锁和解锁必须在一个数据库连接里,否则会出现解锁失败的情况。

二 并发机制底层实现原理

1.volatile原理

作用:如果一个字段被声明成volatile,Java线程内存模型确保所有线程看到这个变量的值是一致的
原理: 从汇编之后的代码可看出volatile修饰变量写操作会有一个Lock操作
在这里插入图片描述
对volatile变量进行写操作时,JVM会向处理器发送一条Lock前缀的指令,将这个变量所在的缓存行的数据写回至系统内存。这时,其他处理器缓存的值是旧的,因此,在多处理器下,为保证各个处理器的缓存一致,就会实现缓存一致性协议,每个处理器通过嗅探在总线上传播的数据来检查自己缓存的值是不是过期了,当处理器发现自己缓存行对应的内存地址被修改,就会将当前处理器的缓存行设置成无效状态,当处理器对这个数据进行修改操作的时候,会重新从系统内存中把数据读到处理器缓存里

两个实现原则:
    1)Lock前缀指令会引起处理器缓存回写到内存
    2)一个处理器的缓存回写到内存会导致其他处理器的缓存无效

2.synchronized原理

使用方式:
    1)对于普通同步方法,锁是当前实例对象
    2)对于静态同步方法,锁是当前类的Class对象
    3)对于同步方法块,锁是Synchonized括号里配置的对象

原理:
①JVM基于进入和退出Monitor对象来实现方法同步和代码块同步;
②代码块同步是使用monitorenter和monitorexit指令实现的,而方法同步是使用另外一种方式实现的;
③monitorenter指令是在编译后插入到同步代码块的开始位置,而monitorexit是插入到方法结束处和异常处,JVM要保证每个monitorenter必须有对应的monitorexit与之配对。任何对象都有一个monitor与之关联,当且一个monitor被持有后,它将处于锁定状态。线程执行到monitorenter指令时,将会尝试获取对象所对应的monitor的所有权,即尝试获得对象的锁;

锁升级与对比:
    从低到高依次是:无锁状态、偏向锁状态、轻量级锁状态和重量级锁状态,这几个状态会随着竞争情况逐渐升级
在这里插入图片描述

3.原子类实现原理

使用基于对缓存加锁或总线加锁的方式来实现多处理器之间的原子操作,处理器会自动保证基本的内存操作的原子性;

CAS存在的三大问题

①ABA问题
②循环时间长开销大:自旋
③只能保证一个共享变量的原子操作

三 内存模型

并发编程两个关键问题:通信 + 同步
JVM抽象结构图:

JMM通过控制主内存与每个线程的本地内存之间的交互,来为Java程序员提供内存可见性保证

1.指令重排

     1:编译器重排序
     2 3:处理器重排序

Happen-Before原则:
1)程序顺序规则:一个线程中的每个操作,happens-before于该线程中的任意后续操作
2)监视器锁规则:对一个锁的解锁,happens-before于随后对这个锁的加锁
3)volatile变量规则:对一个volatile域的写,happens-before于任意后续对这个volatile域的读
4)传递性:如果A happens-before B,且B happens-before C,那么A happens-before C
5)start()规则:如果线程A执行操作ThreadB.start()(启动线程B),那么A线程的ThreadB.start()操作happens-before于线程B中的任意操作
6)join()规则:如果线程A执行操作ThreadB.join()并成功返回,那么线程B中的任意操作happens-before于线程A从ThreadB.join()操作成功返回

ReentrantLock
类图:

公平锁的加锁过程:
1)ReentrantLock:lock()
2)FairSync:lock()
3)AbstractQueuedSynchronizer:acquire(int arg)
4)ReentrantLock:tryAcquire(int acquires)

解锁过程:
1)ReentrantLock:unlock()
2)AbstractQueuedSynchronizer:release(int arg)
3)Sync:tryRelease(int releases)

四 并发编程基础

1.概念

2.优先级

3.线程状态

在这里插入图片描述

4.Daemon线程

5.基本操作

启动终止
中断操作
安全终止线程方式:标记字段

6.线程通信

volatile
synchronized
wait+notify
管道输入/输出流
join
ThreadLocal
【案例】
1.简单数据库连接池实例
2.Web服务器Demo

五 锁

1.Lock锁

Lock lock = new ReentrantLock()

①对比Synchronized的特性:
在这里插入图片描述
②API:
在这里插入图片描述

2.队列同步器 AbstractQueuedSynchronizer

队列同步器AbstractQueuedSynchronizer(以下简称同步器),是用来构建锁或者其他同步组件的基础框架,它使用了一个int成员变量表示同步状态,通过内置的FIFO队列来完成资源获取线程的排队工作;

实现方式:继承重写方法
在这里插入图片描述
在这里插入图片描述

class Mutex implements Lock {
    // 静态内部类,自定义同步器
    private static class Sync extends AbstractQueuedSynchronizer {
        // 是否处于占用状态
        @Override
        protected boolean isHeldExclusively() {
            return getState() == 1;
        }
        // 当状态为0的时候获取锁
        @Override
        public boolean tryAcquire(int acquires) {
            if (compareAndSetState(0, 1)) {
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            } return false;
        } // 释放锁,将状态设置为0
        @Override
        protected boolean tryRelease(int releases) {
            if (getState() == 0) {
                throw new IllegalMonitorStateException();
            }
            setExclusiveOwnerThread(null);
            setState(0);
            return true;
        } // 返回一个Condition,每个condition都包含了一个condition队列
        Condition newCondition() { return new ConditionObject(); }
    } // 仅需要将操作代理到Sync上即可
    private final Sync sync = new Sync();
    @Override
    public void lock() { sync.acquire(1); }
    @Override
    public boolean tryLock() { return sync.tryAcquire(1); }
    @Override
    public void unlock() { sync.release(1); }
    @Override
    public Condition newCondition() { return sync.newCondition(); }
    public boolean isLocked() { return sync.isHeldExclusively(); }
    public boolean hasQueuedThreads() { return sync.hasQueuedThreads(); }
    @Override
    public void lockInterruptibly() throws InterruptedException {
        sync.acquireInterruptibly(1);
    }
    @Override
    public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
        return sync.tryAcquireNanos(1, unit.toNanos(timeout));
    }
}

AQS实现分析

1.同步队列
2.独占式同步状态获取与释放
3.共享式同步状态获取与释放
4.独占式超时获取同步状态

3.重入锁

定义:重进入是指任意线程在获取到锁之后能够再次获取该锁而不会被锁所阻塞;
解决2个问题:
     1)线程再次获取锁: 锁需要去识别获取锁的线程是否为当前占据锁的线程,如果是,则再次成功获取;
     2)锁的最终释放: 线程重复n次获取了锁,随后在第n次释放该锁后,其他线程能够获取到该锁。锁的最终释放要求锁对于获取进行计数自增,计数表示当前锁被重复获取的次数,而锁被释放时,计数自减,当计数等于0时表示锁已经成功释放;

//ReentrantLock的nonfairTryAcquire方法
final boolean nonfairTryAcquire(int acquires) {
    final Thread current = Thread.currentThread();
    int c = getState();
    if (c == 0) {
        if (compareAndSetState(0, acquires)) {
            setExclusiveOwnerThread(current);
            return true;
        }
    }
    else if (current == getExclusiveOwnerThread()) {
        int nextc = c + acquires;
        if (nextc < 0) // overflow
            throw new Error("Maximum lock count exceeded");
        setState(nextc);
        return true;
    }
    return false;
}

4.读写锁 ReentrantReadWriteLock

在这里插入图片描述

5.Condition

在这里插入图片描述
实现原理

六 并发容器和框架

1.ConcurrentHashMap

HashMap并发环境的缺点
ConcurrentHashMap的优点
ConcurrentHashMap的结构,初始化方式,操作(get、put、size)

2.ConcurrentLinkedQueue

3.阻塞队列

在这里插入图片描述

4.Fork/join

MapReduce原理

七 13个原子操作类

java.util.concurrent.atomic
getAndIncrement实现原理:

public final int getAndIncrement() {
    for (;;) {
        int current = get();
        int next = current + 1;
        if (compareAndSet(current, next))
            return current;
    }
}
public final boolean compareAndSet(int expect, int update) {
    return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}

八 并发工具类

CountDownLatch
CyclicBarrier
Semaphore
Exchanger:线程之间交换数据

九 线程池

①功能:1.降低资源消耗;2.提高相应速度;3.提高线程可管理性
②处理流程:
        1)线程池判断核心线程池里的线程是否都在执行任务。如果不是,则创建一个新的工作线程来执行任务。如果核心线程池里的线程都在执行任务,则进入下个流程;
        2)线程池判断工作队列是否已经满。如果工作队列没有满,则将新提交的任务存储在这个工作队列里。如果工作队列满了,则进入下个流程;
        3)线程池判断线程池的线程是否都处于工作状态。如果没有,则创建一个新的工作线程来执行任务。如果已经满了,则交给饱和策略来处理这个任务;

③核心参数+参数含义

new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime,
milliseconds,runnableTaskQueue, handler);

④任务提交线程池+关闭线程池
⑤线程池参数分配
⑥监控

十 Executor框架

1.四种ThreadPoolExecutor详解

2.FuntureTask

异步计算
在这里插入图片描述
当一个线程需要等待另一个线程把某个任务执行完后它才能继续执行,此时可以使用FutureTask。假设有多个线程执行若干任务,每个任务最多只能被执行一次。当多个线程试图同时执行同一个任务时,只允许一个线程执行任务,其他线程需要等待这个任务执行完后才能继续执行;

十一 并发编程实践

生产者消费者模式
线上问题的定位方法

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

《Java并发编程的艺术》知识点 的相关文章

  • SQL 错误:“没有这样的表”

    我试图解决为什么我的代码为所有查询返回 null 的原因 最后发现 sql 查询什么也没有返回 我使用简约代码创建了一个新的 AIR 文档 s WindowedApplication
  • 给定“java.sql.SQLIntegrityConstraintViolationException”是否可以确定错误的列

    鉴于我有一个类型为 java sql SQLIntegrityConstraintViolationException 的异常 是否可以以编程方式确定错误的列 或多列 我问这个问题是因为我想将错误映射回客户端的数据模型以指示错误的字段 例如
  • date_sub 对于 mysql 可以,对于 postgresql 可以

    此查询适用于 mySQL 不适用于 Postgresql select from where id and h gt date sub now INTERVAL 30 MINUTE 错误是 Query failed ERREUR erreu
  • 如何在 MySQL 中求和时间?

    正如您在图片中看到的 我有一份停机报告 显示了所选工厂在选定日期的停机时间 现在我想添加所有的值 Time Duration 列并将其显示在附近的单独显示中 TOTAL TIME DURATION 例如 在图像中 所选日期为 2015 年
  • covertJSONtoSQL 在 NiFi 中返回空值

    我正在设计一项工作 使用以下命令将数据从 MySQL 中的数据库转移到另一个数据库 MySQL 执行SQL处理器随后将Avro转换为Json then 将Json转换为SQL then PutSQL如下流程图所示 将JSON转换为SQL返回
  • MySQL 通过 current_timestamp 选择上个月的数据

    直到今天 当我使用 MySQL 并需要对日期 时间执行操作时 我使用带有 unix 时间戳的 int 列 没有出现任何问题 但今天在阅读了一些指南后 我决定默认使用 current timestamp 测试时间戳列 所以我感兴趣如何按列选择
  • PL/pgSQL SELECT 到数组中

    这是我的函数声明和主体的一部分 CREATE OR REPLACE FUNCTION access update RETURNS void AS DECLARE team ids bigint BEGIN SELECT INTO team
  • MySQL 8 用逗号分割字符串并将其转换为JSON ARRAY

    我有以下字符串 a b c d 我想将它转换成一个 json 数组 像这样 a b c d MySQL 8 有什么函数可以实现这个功能吗 Try SELECT CAST CONCAT REPLACE a b c d AS JSON See
  • 如何在 DB2 AS/400 中将小数字段转换为日期字段?

    我有一个 DECIMAL 字段 其中包含 AS400 格式的日期 1100614 我努力了 cast MYDATE as DATE 但我无法将 DECIMAL 转换为 DATE 而 DATE MYDATE 返回空值 如何将此字段转换为日期字
  • SQL 查询用于计算每个客户的订单数量和总金额

    我有两张桌子Order与列 OrderID OrderDate CID EmployeeID And OrderItem与列 OrderID ItemID Quantity SalePrice 我需要返回客户 ID CID 每个客户的订单数
  • 检查两个“select”是否相等

    有没有办法检查两个 非平凡的 选择是否等效 最初我希望两个选择之间有形式上的等价 但是答案在证明 sql 查询等价性 https stackoverflow com questions 56895 proving sql query equ
  • 如果 Row1 = 值 1,则更新其他行

    我有一个小的 php 脚本 用于访问 mySql 数据库 我想在数据库中插入新记录之前查看该数字 值 1 是否等于数据库中的记录 这也在第 1 行 所以我想 查看传入的电话号码是否等于数据库中的电话号码 如果是这样 则必须保持电话号码相同的
  • 无法在 Mac 上启动 MySQL

    使用 Brew 安装后 我无法运行 MySQL 我使用的是 OS X El Capitan 版本 10 11 3 和 MySQL Server 版本 5 7 11 当我启动服务器时 我收到 启动 MySQL 错误 服务器退出而不更新 PID
  • sql查询获取从一月到当月的所有数据,即使没有记录

    我不擅长 sql 所以任何帮助世界都很棒 我有一个 SQL 查询 可以获取从一月到当月注册的记录 我的代码示例 SELECT DatePart YEAR p createStamp as TheYear DatePart MONTH p c
  • 错误代码:1305。函数或过程不存在

    因此 我在 MySQL 中创建一个函数 然后尝试向用户授予使用该函数的权限 但我无法这样做 这就是我正在做的 DELIMITER USE rxhelp36 scbn DROP FUNCTION IF EXISTS businessDayDi
  • MySQL 排序顺序 - 排序规则?

    我在对 MySQL 中的 char 字段进行排序时遇到困难 问题是重音字符与非重音字符混淆 例如 Abc bd Acc 我认为这可能与整理有关 所以我将表格的排序规则更改为utf8 ut8 bin 看完之后这个帖子 https stacko
  • 如何通过子 POJO 的属性过滤复合 ManyToMany POJO?

    我有两个像这样的房间实体 Entity public class Teacher implements Serializable PrimaryKey autoGenerate true public int id ColumnInfo n
  • 非常大的字段会对 MySQL 数据库产生负面影响吗?

    我目前正在使用 Django 构建一个网站 并希望托管用户生物样式页面 该页面可能长达几 KB 这些字段不一定需要搜索 但在查找用户名时确实需要提供 将这些数据存储在数据库中会产生负面影响吗 如果我使用带有数据库链接的静态文本文件 我的服务
  • 如何从批量数据中的mysql列中删除所有非数字字符

    我想从列中删除所有非数字字符 我的数据库中有大量数据 目前我正在使用以下链接中描述的方法 http venerableagents wordpress com 2011 01 29 mysql numeric functions http
  • 数据库字段中的逗号分隔值

    我有一个产品表 该表中的每一行对应一个产品 并由唯一的 ID 标识 现在 每个产品都可以有多个与该产品关联的 代码 例如 Id Code 0001 IN ON ME OH 0002 ON VI AC ZO 0003 QA PS OO ME

随机推荐

  • R语言零基础入门教程 第五章 高级绘图(3)lattice包绘图工具 ggplot2包绘图工具 交互式绘图工具简介交互式绘图工具简介ggplot

    关注公众号凡花花的小窝 收获更多的考研计算机专业编程相关的资料 ggplot2中采用 来添加图层 ggplot2中图层的概念和PS中图层的概念很像 可以这样理解ggplot2中的图层 每个图层可以代表一个图形组件 例如下面要介绍的几何对象
  • 网络爬虫:URL链接中含{}时,运用format输出的变化特例

    示例 维基百科日本检索 keyword 漫画 https ja wikipedia org w index php title E7 89 B9 E5 88 A5 E6 A4 9C E7 B4 A2 limit 20 offset 0 ns
  • Image Manipulation:StyleCLIP:Text-Driven Manipulation of StyleGAN Imagery(2021)

    StyleCLIP Text Driven Manipulation of StyleGAN Imagery StyleCLIP 摘要 受StyleGAN在各种领域中生成高质量逼真的图像的能力的启发 许多新工作集中在理解如何使用StyleG
  • modelsim 关联 notepad++

    modelsim 控制窗口敲入 1 proc external editor filename linenumber exec I notepad notepad exe filename 2 set PrefSource altEdito
  • 车辆遇险有eCall,eCall是什么?

    如果开车时突发心梗 如何才能快速求救 如果遇到严重车祸 陷入昏迷无法求救怎么办 如果半夜车辆侧翻 移动困难 手机也不在身边如何对外求救 这时候 紧急呼叫系统eCall就发挥了作用 它能在汽车发生事故时被动激活 把紧急信息发送给救援平台 以此
  • 三相电表接线图

    三相电表主要用于工厂等负荷较大得场景中 而客户使用三相电表时问题最多的就是三相电表的接线方法 因此湖南云集就为大家介绍一下三相电表的接线方法和三相电表接线图 供大家参考 三相电表分为三相三线电表和三相四线电表 主要的接线方式有三种 直接接入
  • 数据库——SQL语句(查询操作)

    目录 1 单表查询 1 1 按列名选择 1 2 含有表达式 1 3 给列起别名 1 4 取消重复行 1 5 条件查询 1 6 排序 1 7 限制返回行数 1 8 聚集函数 统计个数 求和 求平均值 求极值 1 9 分组 1 10 聚集函数后
  • Postman —— 配置环境变量

    PostMan是一套比较方便的接口测试工具 但我们在使用过程中 可能会出现创建了API请求 但API的URL会随着服务器IP地址的变化而改变 这样的情况下 如果每一个API都重新修改URL的话那将是非常的麻烦 所以PostMan中也提供环境
  • python数据挖掘分析案例python_Python 数据挖掘实例 决策树分析

    友情提示 此篇文章大约需要阅读 7分钟57秒 不足之处请多指教 感谢你的阅读 安装Anaconda Python集成环境 下载环境 anaconda下载选择 安装环境 下载过程中使用默认 但有一个页面需要确认 如下图 anaconda选择页
  • android4.4.2 以太网代理,Android2.3.4系统添加Ethernet框架支持

    参照网上的移植过一次 有以下3个问题先需要注意 一 下载相应的android x86版本代码 否则出错的几率很大 二 如出现android net ethernet ethernetstatetracker cpp stripped of
  • RabbitMQ的transaction、confirm、ack三个概念的解释

    在使用RabbitMQ的过程中 肯定会遇到这样的几个概念 transaction confirm ack 本文介绍一下这几个概念 以及他们之间的关系 RabbitMQ是采用的AMQP协议 AMQP协议定义了 确认 acknowledgeme
  • MySQL基础总结

    首先 今天学习遇到一点小问题 mysql中出现 Unknown column xxx in having clause 这是因为在使用group by分组时 后面如果需要再加一个having进行判断 则所判断的字段需要在select后面出现
  • 【计算机视觉

    文章目录 一 CSPResNeXt 二 ProxylessNet Mobile 三 ProxylessNet CPU 四 RandWire 五 MCKERNEL 六 Assemble ResNet 七 Convolution enhance
  • 短信信息服务器保存时效,长时间保存信息

    长时间保存信息 内容精选 换一换 华为云帮助中心 为用户提供产品简介 价格说明 购买指南 用户指南 API参考 最佳实践 常见问题 视频帮助等技术文档 帮助您快速上手使用华为云服务 向YARN服务器提交MapReduce任务后 客户端提示如
  • CentOS8结束生命周期后如何切换镜像源

    CentOS8结束生命周期后如何切换镜像源 官方提供了一个替代源 但不再进行任何更新 仅提供软件包 CentOS8系统在国内推荐使用阿里云的镜像源 具体切换过程如下 备份现有的repo配置文件 rename repo repo bak et
  • 【Python三大结构练习3】

    1 温度转换 题目描述 输入摄氏温度 华氏温度 输出对应的华氏温度 摄氏温度 这里采用82F表示华氏82度 采用28C表示摄氏28度 实数部分是温度值 转换算法 C F 32 1 8 F C 1 8 32 其中 C表示摄氏温度 F表示华氏温
  • [其他]IDEA中Maven项目配置国内源

    配置国内源主要解决了 在maven项目中pom xml下载jar包失败或过慢的问题 在IDEA中的设置分成两种 设置当前项目与新创项目 我们就需要两种都进行设置 不然只有在当前项目配置了国内源 新创项目的时候还是默认的状态 由于下面两种设置
  • msvcr120.dll丢失的解决方法-一键解决提示msvcr120.dll丢失问题

    msvcr120 dll是的动态链接库文件之一 它在Windows操作系统中发挥着重要的作用 它提供了应用程序所需的各种功能和方法 该文件返回编译后的代码所需的支持库 msvcr120 dll包含用于C C 编译器生成的应用程序所需的重要功
  • 区块链的结构和原理

    区块链的结构和原理 文章目录 区块链的结构和原理 区块链原理 区块链结构 关于区块链的几个问题 结语 区块链原理 区块链是一个链表 链表上存有交易信息 所有人共享同一个链表 因此它也是一个没有管理员的分布式数据库 即去中心化数据库 所有人都
  • 《Java并发编程的艺术》知识点

    目录 一 并发编程挑战 1 上下文切换 2 死锁 二 并发机制底层实现原理 1 volatile原理 2 synchronized原理 3 原子类实现原理 CAS存在的三大问题 三 内存模型 1 指令重排 四 并发编程基础 1 概念 2 优