


目录
一、线程创建(二):Thread类的构造方法、线程运行(二):Thread类的重写run方法
二、锁(四)synchronized&ReentrantLock
[1.new CountDownLatch(int count)](#1.new CountDownLatch(int count))
五、线程安全(一).5:总&线程安全(二).3:总&修改过期
[1.写写之间 - 线程安全(一).5:总](#1.写写之间 - 线程安全(一).5:总)
[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.1先写后读 - 线程安全(二).3:总](#2.1先写后读 - 线程安全(二).3:总)
[2.1.4解决 - 刷新内存](#2.1.4解决 - 刷新内存)
[2.2先读后写 - 修改过期](#2.2先读后写 - 修改过期)
[2.2.4改善 - 写时拷贝(无法避免随机调度有先读后写有旧值)](#2.2.4改善 - 写时拷贝(无法避免随机调度有先读后写有旧值))
1.Collections.synchronizedGather(gather)
[扩容迁移的写写并发时 写块已串行安全](#扩容迁移的写写并发时 写块已串行安全)
一、线程创建(二):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)方法调用
方法调用时 优先以已类方法执行 如查对象向上转型 而来 就下到执行转型层的重写方法
二、锁(四)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.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:总
知识连接:

2.1.1起因
多个线程 并发****先写后读 同一变量
2.1.2原因
内存++可见性++
2.1.3现象
②内存位置可见旧值
++读取不到++ 已执写最新值所在的内存 使得 读取非时新值
2.1.4解决 - 刷新内存
volatile、synchronized 强制读写 共同的主内存
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 或 在桶红黑树时的节点级锁实现