Java并发编程核心的基础知识

目录

一、线程创建(二):Thread类的构造方法、线程运行(二):Thread类的重写run方法

1.Thread的构造方法

Thread作Worker类成员时

2.Thread的重写run方法

Thread作Worker类成员时

(1)从己类Thread出发本层执行run

(2)从己接口Runnable出发下层执行run

(1&2)方法调用

二、锁(四)synchronized&ReentrantLock

1.synchronized

1.1加解锁

synchronized加锁失败:

1.2锁对象

1.3公平性

1.4自协调

2.ReentrantLock

2.1加解锁

2.1.1lock加锁失败:

2.1.2trylock加锁失败:

2.2锁对象

2.3公平性

2.4自协调

三、信号量

1.限制同执线程数

1.1锁

1.2共享锁

2.申请释放资源

2.1acquire

2.2release

四、闭锁CountDownLatch类

[1.new CountDownLatch(int count)](#1.new CountDownLatch(int count))

2.countDown

3.await

五、线程安全(一).5:总&线程安全(二).3:总&修改过期

[1.写写之间 - 线程安全(一).5:总](#1.写写之间 - 线程安全(一).5:总)

1.1起因

1.2原因

1.3现象

1.3.1读取用前过期

①过期旧值

①.1用前过期旧值

①.2用后过期旧值

1.3.2写入片段覆损

[1.4解决 - 串行化](#1.4解决 - 串行化)

[1.4.1防止读取用前过期 => 写块读取的数据 撑得住新](#1.4.1防止读取用前过期 => 写块读取的数据 撑得住新)

[1.4.1.1防用前另使用过期 -> 读串行](#1.4.1.1防用前另使用过期 -> 读串行)

[1.4.1.2防用前另修改过期 -> 读写之间串行](#1.4.1.2防用前另修改过期 -> 读写之间串行)

[1.4.2防止写入片段覆损 => 写块写入的数据 完整无损 -> 写串行](#1.4.2防止写入片段覆损 => 写块写入的数据 完整无损 -> 写串行)

2.读写之间

[2.1先写后读 - 线程安全(二).3:总](#2.1先写后读 - 线程安全(二).3:总)

2.1.1起因

2.1.2原因

2.1.3现象

②内存位置可见旧值

[2.1.4解决 - 刷新内存](#2.1.4解决 - 刷新内存)

[2.2先读后写 - 修改过期](#2.2先读后写 - 修改过期)

2.2.1起因

2.2.2原因

2.2.3现象

[2.2.4改善 - 写时拷贝(无法避免随机调度有先读后写有旧值)](#2.2.4改善 - 写时拷贝(无法避免随机调度有先读后写有旧值))

2.2.4.1利端

2.2.4.1.1写读内存只见一次

2.2.4.1.2写写之间线程安全

2.2.4.1.3读取数据新旧隔套

2.2.4.2弊端

2.2.4.2.1拷贝低效

2.2.4.2.2丢失数据

六、集合的线程安全

1.Collections.synchronizedGather(gather)

2.哈希表的线程安全

2.1Hashtable

2.2ConcurrentHashMap

[扩容迁移的写写并发时 写块已串行安全](#扩容迁移的写写并发时 写块已串行安全)

(1)原标的桶节点锁

(2)新表的CAS、红黑树节点级锁


一、线程创建(二):Thread类的构造方法、线程运行(二):Thread类的重写run方法

知识连接:

线程创建(一):可以/需要重写的方法、线程运行(一):Java程序的运行

1.Thread的构造方法

Thread类 传参初始化Runnable成员 进行构造

Thread作Worker类成员时

Worker类 ->【JavaEE】线程池ThreadPoolExecutor源码2w字详解 - CSDN博客

  • Worker类 实现Runnable接口 的重写run方法 ++执行外部类ThreadPoolExecutor的runWorker方法++

Thread成员构造时 传++自身Worker类实例++参this ++向上转型++初始化 ++Thread里存储的++ Runnable成员target


2.Thread的重写run方法

  • Thread类 实现Runnable接口 的重写run方法 ++执行Thread类存储的一个Runnable成员任务target++

Thread作Worker类成员时

(1)从己类Thread出发本层执行run

Worker类的成员Thread线程 调用start启动后 调用run 优先执行 已类 Thread的重写run方法 thread己身向上转型来 就没往下转 ++执行Thread类本层的run方法 里面再去执行Thread存储的Runnable任务++

(2)从己接口Runnable出发下层执行run

Runnable成员调用run 优先执行 己接口 Runnable的run方法 runnable己身向上转型来下转 到对应子类Worker ++执行转型层的重写run方法++

(1&2)方法调用

【JavaSE】多态 - CSDN博客

方法调用优先以已类方法执行查对象向上转型 而来 就下到执行转型层的重写方法


二、锁(四)synchronized&ReentrantLock

知识连接:

锁(一):对象的锁属性[作用/实现/修饰/危害]

锁(二):位置/阻塞/重入/连续

锁(三):锁策略

1.synchronized

synchronized是关键字,由JVM的C++代码实现

1.1加解锁

代码块加解锁:进代码块加锁出代码块解锁

synchronized加锁失败:

++synchronized加锁竞争失败++ ,锁 阻塞没锁线程 等待锁 唤醒阻塞 再重新去上锁竞争


1.2锁对象

++竞争的锁对象++ 由传入自定义


1.3公平性

默认且只能非公平锁


1.4自协调

锁内部 用Object类的wait/notify方法 ++自定协调++ 进行 弃锁 没锁 被锁阻塞持锁 用锁 唤醒阻塞


2.ReentrantLock

ReentrantLock是,由Java代码实现

2.1加解锁

方法加解锁:lock、trylock方法加锁unlock方法解锁

2.1.1lock加锁失败:

++lock加锁竞争失败++ ,锁 阻塞没锁线程 等待锁 唤醒阻塞 再重新上锁竞争

2.1.2trylock加锁失败:

++trylock加锁竞争失败++ ,返回false(++加锁竞争成功++ ,返回true),++时间参数等待时间再返回++


2.2锁对象

++竞争的锁对象++ 是自身实例


2.3公平性

默认非公平锁构造传true 实现公平锁


2.4自协调

锁内部 用Condition类的等待/通知方法 ++自定协调++ 进行 弃锁 没锁 被锁阻塞持锁 用锁 唤醒阻塞


三、信号量

信号量 计数 ++供给线程占用++ 的资源个数

1.限制同执线程数

++一个线程 可以持有 信号量的多个资源++ ,限制了++每个线程在持有最少一个资源 下的++++最多同时执行的线程个数++

1.1锁

总供给1个资源的 二元信号量,限制 同时++最多1个++线程 持有资源执行 ,即++++

1.2共享锁

总供给个资源的 多元信号量,限制 同时++可以++++多个++ 线程** 持有资源执行** ,即++共享锁++


2.申请释放资源

2.1acquire

线程申请资源P操作

2.2release

线程释放资源V操作


四、闭锁CountDownLatch类

1.new CountDownLatch(int count)

初始计数次数

2.countDown

计数减1次

3.await

阻塞线程计数次减完<=0


五、线程安全(一).5:总&线程安全(二).3:总&修改过期

多个线程 并发访问 同一变量 有写

1.写写之间 - 线程安全(一).5:总

知识连接:

线程安全(一).1:不安全原因和措施

线程安全(一).2:指令全排序

线程安全(一).3:条件产生渡送执行

线程安全(一).4:写块串行保安全

1.1起因

多个线程 并发****写 同一 变量

1.2原因

写块++非原子++


1.3现象

非原子写块++互碎++ 使得 ++写块的 读取用前过期写入片段覆损++

1.3.1读取用前过期
①过期旧值

"****读取的数据读的变量 使用/修改++[++ 互碎另写的碎片来的]后 过期**"**

①.1用前过期旧值

写块互碎后可能发生 读取的数据读取后使用前 有另线程并发 修改/使用读变量用前****过期,++使用过期值++

①.2用后过期旧值

读取的数据读取后使用后 再另线程并发 修改/使用读变量 变为 用后****过期的旧值

1.3.2写入片段覆损

" 写入的数据 都会互覆 "

写块互碎后 可能发生 写入的数据 互相在 写到半未写完时片段覆****损


1.4解决 - 串行化

++串行原子化++写块 防止++互碎++ ++的 读取用前过期写入片段覆损++

1.4.1防止读取用前过期 => 写块读取的数据 撑得住新

防止另外线程读取后使用前 并发 使用/修改 读取变量 使读取数据 用前过期

1.4.1.1防用前另使用过期 -> 读串行

读变量1串行 **无外线程并列地 ++并发++**++去读++ 出 串行用下注定排成 读取数据 使用时已用完用前过期的数据

1.4.1.2防用前另修改过期 -> 读写之间串行

读变量1与写变量2串行 无外线程穿插在中间地 ++并发++++写改++ 读变量1 使读取数据 使用前被修改用前****过期

1.4.2防止写入片段覆损 => 写块写入的数据 完整无损 -> 写串行

写变量2串行 无外线程互穿插地 ++并发++****++互写++ 使完整的写 成片段地互相覆盖 覆损数据


2.读写之间

2.1先写后读 - 线程安全(二).3:总

知识连接:

线程安全(二).1:不安全原因和措施

线程安全(二).2:内存可见性

2.1.1起因

多个线程 并发****先写后读 同一变量

2.1.2原因

内存++可见性++

2.1.3现象
②内存位置可见旧值

++读取不到++ 已执写最新值所在的内存 使得 读取非时新值

2.1.4解决 - 刷新内存

volatilesynchronized 强制读写 共同的主内存


2.2先读后写 - 修改过期

2.2.1起因

多个线程 并发先读后写 同一变量

2.2.2原因

线程单位 随机调度****有 所有的相对执行顺序

2.2.3现象

++随机下 一定会有 先读后写 调度++ ,读线程先读取的数据 不管用前被写线程修改读变量而过期 还是自己用后已过期,写线程在后修改读变量后读取数据一定变过期


2.2.4改善 - 写时拷贝(无法避免随机调度有先读后写有旧值)

并发读写相同变量时,每对读写拷贝多一份变量 分开读写内存地 进行并发

2.2.4.1利端
2.2.4.1.1写读内存只见一次

写读并发 分开内存时 不会有 先写后读共同内存的 可见性问题:延后并减少成 只在指针赋值修改后 读取新数组的已修改数据时的一次


2.2.4.1.2写写之间线程安全

原子写写 共同内存并发赋值修改 指针 指向 非原子 写写 各自内存并发修改 好的新数组,指针写写数组写写线程安全


2.2.4.1.3读取数据新旧隔套

读写并发 分开内存时 不会有 先读后写共同变量的 修改过期问题:延后并减少成 只在指针赋值修改 指向改好的新数组后 读取数据 由全新变全旧地 整套地过期一次数据新旧不互掺地隔套读取

应用 - 服务器修改配置

修改服务器的配置文件时,通过 停机服务无读取写时拷贝新旧套读 避免 服务器读取 ++新旧互掺++的配置

(1)停机服务

服务器停机 关闭服务客户端 无配置读取地 修改配置

(2)写时拷贝

启动 ++单个++ 修改配置的++写++线程读取配置的++多个读++线程 只构成++一对读写++++拷贝一份++原配置

(2).1线程安全

++单个写++线程 修改原配置++多个读++线程 读取拷贝的共同一个配置 线程安全

(2).2不丢数据

只构成++一对读写++ 只有++一个新数组++ 修改数据不会被整数组互覆盖丢失

(2).3新旧套隔

  • 写线程修改完配置前:读线程全新地读取配置
  • 写线程修改完配置更新指针后:读线程读取的配置由全新变全旧地 整套过期

读取的配置 新旧隔套 不会互掺


2.2.4.2弊端
2.2.4.2.1拷贝低效

多对地并发 读写相同变量 且 变量内存巨大 时,拷贝 多份巨大的变量 开销很大

2.2.4.2.2丢失数据

多对地 并发读写 相同变量时修改数据零散独立在多个新数组中 被整数组互覆盖丢失


六、集合的线程安全

1.Collections.synchronizedGather(gather)

集合的公共方法 加上synchronized锁修饰


2.哈希表的线程安全

2.1Hashtable

Hashtable全部方法整表this实例 上锁 串防 对表的所有并发操作

2.2ConcurrentHashMap

ConcurrentHashMap写方法修改所处桶的头节点 上锁 串防 ++只在同桶区域++ ++才有可能对同节点 才可能有危险++ 的并发有写操作

扩容迁移的写写并发时 写块已串行安全
(1)原标的桶节点锁

写块的 读串行读写间串行 用++原表++ 的桶节点锁实现

(2)新表的CAS、红黑树节点级锁

写块的 写串行 用++新表++ 在桶链表时的CAS尾插next 或 在桶红黑树时的节点级锁实现

相关推荐
智航GIS2 分钟前
ArcGIS Python零基础脚本开发教程---1.1 Describe 函数
开发语言·python·arcgis
云游云记6 分钟前
php 网络请求工具全解:cURL 与 Guzzle 总结
开发语言·网络·php
华农第一蒟蒻7 分钟前
一次服务器CPU飙升的排查与解决
java·运维·服务器·spring boot·arthas
m0_7482299915 分钟前
帝国CMS后台搭建全攻略
java·c语言·开发语言·学习
weixin_4624462321 分钟前
PaddleX 3.2 人脸识别实战:自定义人脸库 + CartoonFace 官方案例 Top-K 识别完整指南
开发语言·r语言
Testopia37 分钟前
走一遍 AI 学习之路 —— AI实例系列说明
开发语言·人工智能·python
码农娟38 分钟前
Hutool XML工具-XmlUtil的使用
xml·java
Tony Bai40 分钟前
【分布式系统】11 理论的试金石:用 Go 从零实现一个迷你 Raft 共识
开发语言·后端·golang
Beginner x_u40 分钟前
JavaScript 原型、原型链与原型继承的核心机制解析
开发语言·javascript·原型模式·原型原型链
离离茶40 分钟前
【笔记1-11】Qt 关闭QToolbar的拓展菜单
开发语言·笔记·qt