《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并发编程的艺术》知识点 的相关文章

  • C# using 语句、SQL 和 SqlConnection

    使用 using 语句 C SQL 可以吗 private static void CreateCommand string queryString string connectionString using SqlConnection c
  • MySQL - 选择一行 - 然后相对于所选行的下一个和上一个

    我会尽力澄清这一点 我需要在不使用 id 的情况下选择特定行和该选定行的前一个相对行以及该选定行的下一个相对行 这可能吗 简而言之 上一篇和下一篇 我不能 也许我只是不知道如何 使用 id 的原因是因为它们不是按顺序排列的 正如您从这个相当
  • “pdo_mysql”已禁用,我无法启用它。我在 iMac 7.1 OSX 10.6.8 上安装了 MAMP v. 3.0.4

    pdo mysql 已禁用 我无法启用它 我在 iMac 7 1 OSX 10 6 8 上安装了 MAMP v 3 0 4 在我的 phpinfo 页面上 我可以看到唯一启用的 PDO 是 sqlite 如果我查看 php 5 5 10 扩
  • 以编程方式插入行(父行和子行)

    我正在使用 Spring 和 JDBCTemplate 该场景是 CUSTOMER 表和 ORDERS 表的父子关系 我想做一个插入 例如 1 个客户和 5 个订单 但我不确定如何以编程方式在 CUSTOMER 表中插入一行 如何获取 Or
  • 何时在 mysql 中使用 Union [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 对于 Union 您会在什么现实情况下使用它 因为对我来说 对具有不同列用途 含义的两个表中的两个选择查询使用联合是没有意义的 例如
  • 使用联接更新表?

    我正在尝试使用表 B 中的数据更新表 A 我以为我可以做这样的事情 update A set A DISCOUNT 3 from INVOICE ITEMS A join ITEM PRICE QUNTITY B on A ITEM PRI
  • 在上下文中提取搜索字符串

    我正在尝试执行 MySQL 查询 在上下文中提取搜索字符串 因此 如果搜索是 mysql 我想从 body 列返回类似的内容 下载后只需几分钟MySQL安装程序即可使用 这就是我现在得到的 但它不起作用 因为它只是从正文字段中获取前 20
  • 如何将行变成列?

    我有一个数据库 其中存储分组到项目中的关键字以及与每个关键字相关的数据 然后我显示每个项目的数据网格 每个关键字一行和几列 全部从同一个表 数据 中检索 我有 4 个表 关键字 项目 group keywords 和数据 keywords
  • 无法在 .net core 2 中从 MySQL 构建“日期”类型列

    我已经开始了一个新的 net core 2 项目 我正在尝试将 MySQL 数据库导入实体框架 我使用此命令来搭建数据库 Scaffold DbContext server localhost port 3306 user id user
  • 如何导出带有数据的 MySQL 架构?

    我有一个完整的架构 其中有许多表 其中包含 MySQL 查询浏览器中的数据 现在我想将这个包含所有表 数据的完整数据库发送给我的同事 我怎样才能将其发送给我的同事 以便他可以将这个完整的架构放入他的 MySQL 查询浏览器中 Thanks
  • MySQL集群启动失败

    这不是我第一次创建ndbcluster 但我没有收到这样的问题 我正在关注本手册 https hub docker com r mysql mysql cluster by mysql团队 我正在使用回显的默认配置在此 GitHub 存储库
  • 猪的组连接等效吗?

    试图在 Pig 上完成这个任务 寻找 MySQL 的 group concat 等效项 例如 在我的表中 我有以下内容 3fields userid clickcount pagenumber 155 2 12 155 3 133 155
  • 加载数据infile,Windows和Linux的区别

    我有一个需要导入到 MySQL 表的文件 这是我的命令 LOAD DATA LOCAL INFILE C test csv INTO TABLE logs fields terminated by LINES terminated BY n
  • 如何拥有引用另一个表的检查约束?

    我在 SQL Server 2008 数据库中有以下表 tblItem 其中有一个ItemID field 好项目 它还有一个 ItemID 字段 并且有一个指向 tblItem 的外键 tblBadItem 它也有一个 ItemID 字段
  • AWS RDS MySql - 如何在设置“公开可用”后允许访问

    刚刚使用默认设置和用户 密码创建了新的 AWS RDS MySql 实例 我也将其设置为publicly available并在此过程中创建新的 VPC 目前无法从我的笔记本电脑连接到此 RDS mysql h endpoint u myu
  • 将布尔参数传递给 SQL Server 存储过程

    我早些时候问过这个问题 我以为我找到了问题所在 但我没有 我在将布尔参数传递给存储过程时遇到问题 这是我的 C 代码 public bool upload false protected void showDate object sende
  • MySQL 左连接 WHERE table2.field = "X"

    我有以下表格 pages Field Type Null Key Default Extra page id int 11 NO PRI NULL auto increment type varchar 20 NO NULL
  • 插入记录后如何从SQL Server获取Identity值

    我在数据库中添加一条记录identity价值 我想在插入后获取身份值 我不想通过存储过程来做到这一点 这是我的代码 SQLString INSERT INTO myTable SQLString Cal1 Cal2 Cal3 Cal4 SQ
  • 更改mysql数据库表中的日期格式

    大家早上好 只是一个简单的问题 在我现有的 MySql 数据库中 我几乎没有包含日期 的列 目前这些是年 月 日格式 但现在我需要将其全部更改为年 月 日格式 我试过了select date format curdate d m Y 但它不
  • Oracle:按月分区表

    我的解决方案 德语几个月 PARTITION BY LIST to char GEBURTSDATUM Month PARTITION p1 VALUES JANUAR PARTITION p2 VALUES Februar PARTITI

随机推荐

  • 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 优