Skip to content

Commit 51ed2ff

Browse files
committed
update docs
1 parent 41521f8 commit 51ed2ff

File tree

5 files changed

+29
-27
lines changed

5 files changed

+29
-27
lines changed
65.4 KB
Binary file not shown.
11.4 KB
Binary file not shown.

docs/concurrent/Java内存模型.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,20 +46,20 @@
4646

4747
为了解决缓存一致性问题,**需要各个处理器访问缓存时都遵循一些协议,在读写时要根据协议来进行操作**
4848

49-
![img](http://dunwu.test.upcdn.net/cs/java/javacore/concurrent/cpu-memory-model.png)
49+
![](https://raw.githubusercontent.com/dunwu/images/dev/snap/20210102230327.png)
5050

5151
### 1.3. 代码乱序执行优化
5252

5353
**除了高速缓存以外,为了使得处理器内部的运算单元尽量被充分利用**,处理器可能会对输入代码进行乱序执行(Out-Of-Order Execution)优化。处理器会在计算之后将乱序执行的结果重组,**保证该结果与顺序执行的结果是一致的**,但不保证程序中各个语句计算的先后顺序与输入代码中的顺序一致。
5454

55-
![img](http://dunwu.test.upcdn.net/cs/java/javacore/concurrent/java-memory-model_1.png)
55+
![](https://raw.githubusercontent.com/dunwu/images/dev/snap/20210102223609.png)
5656

5757
乱序执行技术是处理器为提高运算速度而做出违背代码原有顺序的优化。
5858

5959
- **单核**环境下,处理器保证做出的优化不会导致执行结果远离预期目标,但在多核环境下却并非如此。
6060
- **多核**环境下, 如果存在一个核的计算任务依赖另一个核的计算任务的中间结果,而且对相关数据读写没做任何防护措施,那么其顺序性并不能靠代码的先后顺序来保证。
6161

62-
![img](http://dunwu.test.upcdn.net/cs/java/javacore/concurrent/java-memory-model_2.png)
62+
![](https://raw.githubusercontent.com/dunwu/images/dev/snap/20210102224144.png)
6363

6464
## 2. Java 内存模型
6565

@@ -79,11 +79,11 @@ JMM 规定了**所有的变量都存储在主内存(Main Memory)中**。
7979

8080
每条线程还有自己的工作内存(Working Memory),**工作内存中保留了该线程使用到的变量的主内存的副本**。工作内存是 JMM 的一个抽象概念,并不真实存在,它涵盖了缓存,写缓冲区,寄存器以及其他的硬件和编译器优化。
8181

82-
![img](http://dunwu.test.upcdn.net/cs/java/javacore/concurrent/java-memory-model_3.png)
82+
![](https://raw.githubusercontent.com/dunwu/images/dev/snap/20210102225839.png)
8383

8484
线程对变量的所有操作都必须在工作内存中进行,而不能直接读写主内存中的变量。不同的线程间也无法直接访问对方工作内存中的变量,**线程间变量值的传递均需要通过主内存来完成**
8585

86-
![img](http://dunwu.test.upcdn.net/cs/java/javacore/concurrent/java-memory-model_4.png)
86+
![](https://raw.githubusercontent.com/dunwu/images/dev/snap/20210102225657.png)
8787

8888
> 说明:
8989
>
@@ -125,7 +125,7 @@ JMM 还规定了上述 8 种基本操作,需要满足以下规则:
125125
- 如果一个变量事先没有被 lock 操作锁定,则不允许对它执行 unlock 操作,也不允许去 unlock 一个被其他线程锁定的变量。
126126
- 对一个变量执行 unlock 操作之前,必须先把此变量同步到主内存中(执行 store 和 write 操作)
127127

128-
![img](http://dunwu.test.upcdn.net/cs/java/javacore/concurrent/java-memory-operator.png)
128+
![](https://raw.githubusercontent.com/dunwu/images/dev/snap/20210102230708.png)
129129

130130
### 2.4. 并发安全特性
131131

docs/concurrent/Java线程基础.md

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,9 @@ public class ThreadYieldDemo {
361361

362362
> **`Thread` 中的 `stop` 方法有缺陷,已废弃**
363363
>
364-
> 使用 `Thread.stop` 停止线程会导致它解锁所有已锁定的监视器(由于未经检查的 `ThreadDeath` 异常会在堆栈中传播,这是自然的结果)。 如果先前由这些监视器保护的任何对象处于不一致状态,则损坏的对象将对其他线程可见,从而可能导致任意行为。`Thread.stop` 的许多用法应由仅修改某些变量以指示目标线程应停止运行的代码代替。 目标线程应定期检查此变量,如果该变量指示要停止运行,则应按有序方式从其运行方法返回。如果目标线程等待很长时间(例如,在条件变量上),则应使用中断方法来中断等待。
364+
> 使用 `Thread.stop` 停止线程会导致它解锁所有已锁定的监视器(由于未经检查的 `ThreadDeath` 异常会在堆栈中传播,这是自然的结果)。 如果先前由这些监视器保护的任何对象处于不一致状态,则损坏的对象将对其他线程可见,从而可能导致任意行为。
365+
>
366+
> stop() 方法会真的杀死线程,不给线程喘息的机会,如果线程持有 ReentrantLock 锁,被 stop() 的线程并不会自动调用 ReentrantLock 的 unlock() 去释放锁,那其他线程就再也没机会获得 ReentrantLock 锁,这实在是太危险了。所以该方法就不建议使用了,类似的方法还有 suspend() 和 resume() 方法,这两个方法同样也都不建议使用了,所以这里也就不多介绍了。`Thread.stop` 的许多用法应由仅修改某些变量以指示目标线程应停止运行的代码代替。 目标线程应定期检查此变量,如果该变量指示要停止运行,则应按有序方式从其运行方法返回。如果目标线程等待很长时间(例如,在条件变量上),则应使用中断方法来中断等待。
365367
366368
当一个线程运行时,另一个线程可以直接通过 `interrupt` 方法中断其运行状态。
367369

@@ -407,7 +409,7 @@ public class ThreadInterruptDemo {
407409
- 定义 `volatile` 标志位,在 `run` 方法中使用标志位控制线程终止
408410
- 使用 `interrupt` 方法和 `Thread.interrupted` 方法配合使用来控制线程终止
409411

410-
示例:使用 `volatile` 标志位控制线程终止
412+
【示例】使用 `volatile` 标志位控制线程终止
411413

412414
```java
413415
public class ThreadStopDemo2 {
@@ -447,7 +449,7 @@ public class ThreadStopDemo2 {
447449
}
448450
```
449451

450-
示例:使用 `interrupt` 方法和 `Thread.interrupted` 方法配合使用来控制线程终止
452+
【示例】使用 `interrupt` 方法和 `Thread.interrupted` 方法配合使用来控制线程终止
451453

452454
```java
453455
public class ThreadStopDemo3 {
@@ -717,7 +719,7 @@ public class Piped {
717719

718720
## 5. 线程生命周期
719721

720-
![img](http://dunwu.test.upcdn.net/cs/java/javacore/concurrent/java-thread_1.png)
722+
![](https://raw.githubusercontent.com/dunwu/images/dev/snap/20210102103928.png)
721723

722724
`java.lang.Thread.State` 中定义了 **6** 种不同的线程状态,在给定的一个时刻,线程只能处于其中的一个状态。
723725

@@ -727,27 +729,27 @@ public class Piped {
727729

728730
- **就绪(Runnable)** - 已经调用了 `start` 方法的线程处于此状态。此状态意味着:**线程已经在 JVM 中运行**。但是在操作系统层面,它可能处于运行状态,也可能等待资源调度(例如处理器资源),资源调度完成就进入运行状态。所以该状态的可运行是指可以被运行,具体有没有运行要看底层操作系统的资源调度。
729731

730-
- **阻塞(Blocked)** - 表示线程在等待 Monitor lock,从而进入 `synchronized` 函数或者代码块,但是其它线程已经占用了该 Monitor lock,所以处于阻塞状态。要结束该状态进入 `Runnable`,从而需要其他线程释放 Monitor lock。此状态意味着:**线程处于被阻塞状态**
732+
- **阻塞(Blocked)** - 此状态意味着:**线程处于被阻塞状态**表示线程在等待 `synchronized` 的隐式锁(Monitor lock)。`synchronized` 修饰的方法、代码块同一时刻只允许一个线程执行,其他线程只能等待,即处于阻塞状态。当占用 `synchronized` 隐式锁的线程释放锁,并且等待的线程获得 `synchronized` 隐式锁时,就又会从 `BLOCKED` 转换到 `RUNNABLE` 状态
731733

732-
- **等待(Waiting)** - 此状态意味着:**线程等待被其他线程显式地唤醒**。 阻塞和等待的区别在于,阻塞是被动的,它是在等待获取 Monitor lock。而等待是主动的,通过调用 `Object.wait` 等方法进入。
734+
- **等待(Waiting)** - 此状态意味着:**线程无限期等待,直到被其他线程显式地唤醒**。 阻塞和等待的区别在于,阻塞是被动的,它是在等待获取 `synchronized` 的隐式锁。而等待是主动的,通过调用 `Object.wait` 等方法进入。
733735

734-
| 进入方法 | 退出方法 |
735-
| ------------------------------------------ | ------------------------------------ |
736-
| 没有设置 Timeout 参数的 `Object.wait` 方法 | `Object.notify` / `Object.notifyAll` |
737-
| 没有设置 Timeout 参数的 `Thread.join` 方法 | 被调用的线程执行完毕 |
738-
| `LockSupport.park` 方法 | `LockSupport.unpark` |
736+
| 进入方法 | 退出方法 |
737+
| ------------------------------------------------------------ | ------------------------------------ |
738+
| 没有设置 Timeout 参数的 `Object.wait` 方法 | `Object.notify` / `Object.notifyAll` |
739+
| 没有设置 Timeout 参数的 `Thread.join` 方法 | 被调用的线程执行完毕 |
740+
| `LockSupport.park` 方法(Java 并发包中的锁,都是基于它实现的) | `LockSupport.unpark` |
739741

740742
- **定时等待(Timed waiting)** - 此状态意味着:**无需等待其它线程显式地唤醒,在一定时间之后会被系统自动唤醒**
741743

742-
| 进入方法 | 退出方法 |
743-
| ---------------------------------------- | ----------------------------------------------- |
744-
| `Thread.sleep` 方法 | 时间结束 |
745-
| 设置了 Timeout 参数的 `Object.wait` 方法 | 时间结束 / `Object.notify` / `Object.notifyAll` |
746-
| 设置了 Timeout 参数的 `Thread.join` 方法 | 时间结束 / 被调用的线程执行完毕 |
747-
| `LockSupport.parkNanos` 方法 | `LockSupport.unpark` |
748-
| `LockSupport.parkUntil` 方法 | `LockSupport.unpark` |
744+
| 进入方法 | 退出方法 |
745+
| ------------------------------------------------------------ | ----------------------------------------------- |
746+
| `Thread.sleep` 方法 | 时间结束 |
747+
| 获得 `synchronized` 隐式锁的线程,调用设置了 Timeout 参数的 `Object.wait` 方法 | 时间结束 / `Object.notify` / `Object.notifyAll` |
748+
| 设置了 Timeout 参数的 `Thread.join` 方法 | 时间结束 / 被调用的线程执行完毕 |
749+
| `LockSupport.parkNanos` 方法 | `LockSupport.unpark` |
750+
| `LockSupport.parkUntil` 方法 | `LockSupport.unpark` |
749751

750-
- **终止(Terminated)** - 线程 `run` 方法执行结束,或者因异常退出了 `run` 方法。此状态意味着:线程结束了生命周期。
752+
- **终止(Terminated)** - 线程执行完 `run` 方法,或者因异常退出了 `run` 方法。此状态意味着:线程结束了生命周期。
751753

752754
## 6. 线程常见问题
753755

docs/concurrent/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
77
## 📖 内容
88

9-
### [Java 并发简介](concurrent/Java并发简介.md)
9+
### [Java 并发简介](Java并发简介.md)
1010

1111
> **关键词:`进程``线程``安全性``活跃性``性能``死锁``饥饿``上下文切换`**
1212
@@ -36,7 +36,7 @@
3636

3737
> **关键词:`ConcurrentHashMap``CopyOnWriteArrayList`**
3838
39-
### [Java 线程池](concurrent/Java线程池.md)
39+
### [Java 线程池](Java线程池.md)
4040

4141
> **关键词:`Executor``ExecutorService``ThreadPoolExecutor``Executors`**
4242

0 commit comments

Comments
 (0)