Skip to content

Commit 2c40f49

Browse files
committed
修改MySQL必知必会内容
1 parent 78f3efb commit 2c40f49

12 files changed

Lines changed: 113 additions & 119 deletions

MySQL/MySQL必知必会.md

Lines changed: 47 additions & 50 deletions
Large diffs are not rendered by default.

RedSpiderConcurrent/1.进程与线程的基本概念.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,3 @@ CPU 通过为每个线程分配 CPU 时间片来实现多线程机制。CPU 通
4444
但是,在切换前会保存上一个任务的状态,以便下次切换回这个任务时,可以再加载这个任务的状态。所以任务从保存到再加载的过程就是一次上下文切换。
4545

4646
上下文切换通常是计算密集型的,意味着此操作会 **消耗大量的 CPU 时间,故线程也不是越多越好**
47-

RedSpiderConcurrent/11.AQS.md

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ getState()
88
setState()
99
compareAndSetState()
1010
```
11-
这三种均是原子操作,其中 compareAndSetState 的实现依赖于 Unsafe 的 compareAndSwapInt() 方法。
11+
这三种均是原子操作,其中 compareAndSetState 的实现依赖于 Unsafe 的 `compareAndSwapInt()` 方法。
1212

13-
![](http://concurrent.redspider.group/article/02/imgs/AQS%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84.png)
13+
![](img/AQS数据结构.png)
1414

1515
AQS 内部使用了一个先进先出的双端队列,并使用了两个指针 head 和 tail 用于标识队列的头部和尾部。但它并不是直接存储线程,而是存储拥有线程的 Node 节点。
1616

@@ -65,11 +65,11 @@ private Node addWaiter(Node mode) {
6565
```
6666

6767
### AQS 的主要方法源码
68-
- isHeldExclusively():该线程是否正在独占资源。只有用到 condition 才需要去实现它;
69-
- tryAcquire(int):独占方式。尝试获取资源,成功则返回 true,失败则返回 false;
70-
- tryRelease(int):独占方式。尝试释放资源,成功则返回 true,失败则返回 false;
71-
- tryAcquireShared(int):共享方式。尝试获取资源。负数表示失败;0表示成功,但没有剩余可用资源;正数表示成功,且有剩余资源;
72-
- tryReleaseShared(int):共享方式。尝试释放资源,如果释放后允许唤醒后续等待结点返回 true,否则返回 false。
68+
- `isHeldExclusively()`:该线程是否正在独占资源。只有用到 condition 才需要去实现它;
69+
- `tryAcquire(int)`:独占方式。尝试获取资源,成功则返回 true,失败则返回 false;
70+
- `tryRelease(int)`:独占方式。尝试释放资源,成功则返回 true,失败则返回 false;
71+
- `tryAcquireShared(int)`:共享方式。尝试获取资源。负数表示失败;0表示成功,但没有剩余可用资源;正数表示成功,且有剩余资源;
72+
- `tryReleaseShared(int)`:共享方式。尝试释放资源,如果释放后允许唤醒后续等待结点返回 true,否则返回 false。
7373

7474
上述方法都是 protected 方法,之所以不使用抽象方法的目的是可以灵活的让子类根据需要选择实现某些方法而不是强迫子类实现所有的抽象方法。
7575

@@ -143,9 +143,9 @@ final boolean acquireQueued(final Node node, int arg) {
143143
}
144144
}
145145
```
146-
> parkAndCheckInterrupt方法内部使用了LockSupport.park(this),LockSupport 类是 Java 6 引入的一个类,提供了基本的线程同步原语。LockSupport 实际上是调用了 Unsafe 类里面的函数:
147-
1. park(boolean isAbsolute, long time):阻塞当前线程;
148-
2. unpark(Thread jthread):使给定的线程停止阻塞。
146+
> `parkAndCheckInterrupt()` 方法内部使用了 `LockSupport.park(this)`,LockSupport 类是 Java 6 引入的一个类,提供了基本的线程同步原语。LockSupport 实际上是调用了 Unsafe 类里面的函数:
147+
1. `park(boolean isAbsolute, long time)`:阻塞当前线程;
148+
2. `unpark(Thread jthread)`:使给定的线程停止阻塞。
149149

150150
**所以结点进入等待队列后,是调用 park 使它进入阻塞状态的。只有头结点的线程是处于活跃状态的。**
151151

RedSpiderConcurrent/2.Java 多线程入门类和接口.md

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public class Demo {
2323
}
2424
```
2525

26-
> 注意不可多次调用 start() 方法。在第一次调用 start() 方法后,再次调用 start() 方法会抛出 IllegalThreadStateException 异常。
26+
> 注意不可多次调用 `start()` 方法。在第一次调用 `start()` 方法后,再次调用 `start()` 方法会抛出 IllegalThreadStateException 异常。
2727
2828
#### 实现 Runnable 接口
2929

@@ -94,11 +94,11 @@ ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
9494

9595
#### Thread 类的几个常用方法
9696

97-
- currentThread():静态方法,返回对当前正在执行的线程对象的引用;
98-
- start():开始执行线程的方法,Java 虚拟机会调用线程内的 run() 方法;
99-
- yield():yield 在英语里有放弃的意思,同样,这里的 yield() 指的是当前线程愿意让出对当前处理器的占用。 **这里需要注意的是,就算当前线程调用了 yield() 方法,程序在调度的时候,也还有可能继续运行这个线程的;**
100-
- sleep():静态方法,使当前线程睡眠一段时间;
101-
- join():使当前线程等待另一个线程执行完毕之后再继续执行,内部调用的是 Object 类的 wait 方法实现的。
97+
- `currentThread()`:静态方法,返回对当前正在执行的线程对象的引用;
98+
- `start()`:开始执行线程的方法,Java 虚拟机会调用线程内的 `run()` 方法;
99+
- `yield()`:yield 在英语里有放弃的意思,同样,这里的 `yield()` 指的是当前线程愿意让出对当前处理器的占用。 **这里需要注意的是,就算当前线程调用了 yield() 方法,程序在调度的时候,也还有可能继续运行这个线程的;**
100+
- `sleep()`:静态方法,使当前线程睡眠一段时间;
101+
- `join()`:使当前线程等待另一个线程执行完毕之后再继续执行,内部调用的是 Object 类的 wait 方法实现的。
102102

103103
#### Thread 类与 Runnable 接口的比较:
104104

@@ -111,7 +111,7 @@ ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
111111

112112
#### Callable
113113

114-
Callable 与 Runnable 类似,同样是只有一个抽象方法的函数式接口。不同的是,Callable 提供的方法是 **有返回值** 的,而且支持 **泛型**
114+
Callable 与 Runnable 类似,同样是只有一个抽象方法的函数式接口。不同的是,Callable 提供的方法是**有返回值**的,而且支持**泛型**
115115

116116
```java
117117
@FunctionalInterface
@@ -213,4 +213,3 @@ private static final int INTERRUPTED = 6;
213213
```
214214

215215

216-

RedSpiderConcurrent/4.Java 线程的状态及主要转换方法.md

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44

55
![](img/系统进程状态转换图.png)
66

7-
- 就绪状态(ready):线程正在等待使用 CPU,经调度程序调用之后可进入 running 状态。
8-
- 执行状态(running):线程正在使用 CPU。
9-
- 等待状态(waiting): 线程经过等待事件的调用或者正在等待其他资源(如I/O)。
7+
- 就绪状态ready:线程正在等待使用 CPU,经调度程序调用之后可进入 running 状态。
8+
- 执行状态running:线程正在使用 CPU。
9+
- 等待状态waiting):线程经过等待事件的调用或者正在等待其他资源(如 I/O)。
1010

1111
### Java 线程的六个状态
1212

@@ -26,12 +26,12 @@ public enum State {
2626

2727
处于 NEW 状态的线程此时尚未启动。
2828

29-
**关于 start() 的两个引申问题**
29+
**关于 `start()` 的两个引申问题**
3030

31-
1. 反复调用同一个线程的 start() 方法是否可行?
32-
2. 假如一个线程执行完毕(此时处于 TERMINATED 状态),再次调用这个线程的 start() 方法是否可行?
31+
1. 反复调用同一个线程的 `start()` 方法是否可行?
32+
2. 假如一个线程执行完毕(此时处于 TERMINATED 状态),再次调用这个线程的 `start()` 方法是否可行?
3333

34-
两个问题的答案都是不可行,在调用一次 start() 之后,threadStatus 的值会改变(threadStatus !=0),此时再次调用 start() 方法会抛出 IllegalThreadStateException 异常。比如,threadStatus 为 2 代表当前线程状态为 TERMINATED。
34+
两个问题的答案都是不可行,在调用一次 `start()` 之后,threadStatus 的值会改变(threadStatus !=0),此时再次调用 `start()` 方法会抛出 IllegalThreadStateException 异常。比如,threadStatus 为 2 代表当前线程状态为 TERMINATED。
3535

3636
#### RUNNABLE
3737

@@ -47,70 +47,70 @@ public enum State {
4747

4848
调用如下 3 个方法会使线程进入等待状态:
4949

50-
- Object.wait():使当前线程处于等待状态直到另一个线程唤醒它;
51-
- Thread.join():等待线程执行完毕,底层调用的是 Object 实例的 wait 方法;
52-
- LockSupport.park():除非获得调用许可,否则禁用当前线程进行线程调度。
50+
- `Object.wait()`:使当前线程处于等待状态直到另一个线程唤醒它;
51+
- `Thread.join()`:等待线程执行完毕,底层调用的是 Object 实例的 wait 方法;
52+
- `LockSupport.park()`:除非获得调用许可,否则禁用当前线程进行线程调度。
5353

5454
#### TIMED_WAITING
5555

5656
超时等待状态。线程等待一个具体的时间,时间到后会被自动唤醒。
5757

5858
调用如下方法会使线程进入超时等待状态:
5959

60-
- Thread.sleep(long millis):使当前线程睡眠指定时间;
61-
- Object.wait(long timeout):线程休眠指定时间,等待期间可以通过 notify()/notifyAll() 唤醒;
62-
- Thread.join(long millis):等待当前线程最多执行 millis 毫秒,如果 millis 为 0,则会一直执行;
63-
- LockSupport.parkNanos(long nanos): 除非获得调用许可,否则禁用当前线程进行线程调度指定时间;
64-
- LockSupport.parkUntil(long deadline):同上,也是禁止线程进行调度指定时间。
60+
- `Thread.sleep(long millis)`:使当前线程睡眠指定时间;
61+
- `Object.wait(long timeout)`:线程休眠指定时间,等待期间可以通过 `notify()/notifyAll()` 唤醒;
62+
- `Thread.join(long millis)`:等待当前线程最多执行 millis 毫秒,如果 millis 为 0,则会一直执行;
63+
- `LockSupport.parkNanos(long nanos)`: 除非获得调用许可,否则禁用当前线程进行线程调度指定时间;
64+
- `LockSupport.parkUntil(long deadline)`:同上,也是禁止线程进行调度指定时间。
6565

6666
#### TERMINATED
6767

6868
终止状态。此时线程已执行完毕。
6969

7070
### 线程状态的转换
7171

72-
![](http://concurrent.redspider.group/article/01/imgs/%E7%BA%BF%E7%A8%8B%E7%8A%B6%E6%80%81%E8%BD%AC%E6%8D%A2%E5%9B%BE.png)
72+
![](img/线程状态转换图.png)
7373

7474
#### BLOCKED 与 RUNNABLE 状态的转换
7575

7676
#### WAITING 状态与 RUNNABLE 状态的转换
7777

78-
##### Object.wait()
78+
##### `Object.wait()`
7979

80-
调用 wait() 方法前线程必须持有对象的锁。
80+
调用 `wait()` 方法前线程必须持有对象的锁。
8181

82-
线程调用 wait() 方法时,会释放当前的锁,直到有其他线程调用 notify()/notifyAll() 方法唤醒等待锁的线程。
82+
线程调用 `wait()` 方法时,会释放当前的锁,直到有其他线程调用 `notify()/notifyAll()` 方法唤醒等待锁的线程。
8383

84-
需要注意的是,其他线程调用 notify() 方法只会唤醒单个等待锁的线程,如有有多个线程都在等待这个锁的话不一定会唤醒到之前调用 wait() 方法的线程。
84+
需要注意的是,其他线程调用 `notify()` 方法只会唤醒单个等待锁的线程,如有有多个线程都在等待这个锁的话不一定会唤醒到之前调用 `wait()` 方法的线程。
8585

86-
同样,调用 notifyAll() 方法唤醒所有等待锁的线程之后,也不一定会马上把时间片分给刚才放弃锁的那个线程,具体要看系统的调度。
86+
同样,调用 `notifyAll()` 方法唤醒所有等待锁的线程之后,也不一定会马上把时间片分给刚才放弃锁的那个线程,具体要看系统的调度。
8787

88-
##### Thread.join()
88+
##### `Thread.join()`
8989

90-
调用 join() 方法不会释放锁,会一直等待当前线程执行完毕(转换为 TERMINATED 状态)。
90+
调用 `join()` 方法不会释放锁,会一直等待当前线程执行完毕(转换为 TERMINATED 状态)。
9191

9292
#### TIMED_WAITING 与 RUNNABLE 状态转换
9393

94-
##### Thread.sleep(long)
94+
##### `Thread.sleep(long)`
9595

96-
使当前线程睡眠指定时间。需要注意这里的“睡眠”只是暂时使线程停止执行,并不会释放锁。时间到后,线程会重新进入 RUNNABLE 状态。
96+
使当前线程睡眠指定时间。需要注意这里的“睡眠”只是暂时使线程停止执行,**并不会释放锁**。时间到后,线程会重新进入 RUNNABLE 状态。
9797

98-
##### Object.wait(long)
98+
##### `Object.wait(long)`
9999

100-
wait(long) 方法使线程进入 TIMED_WAITING 状态。这里的 wait(long) 方法与无参方法 wait() 相同的地方是,都可以通过其他线程调用 notify() 或 notifyAll() 方法来唤醒。
100+
`wait(long)` 方法使线程进入 TIMED_WAITING 状态。这里的 `wait(long)` 方法与无参方法 `wait()` 相同的地方是,都可以通过其他线程调用 `notify()``notifyAll()` 方法来唤醒。
101101

102-
不同的地方是,有参方法 wait(long) 就算其他线程不来唤醒它,经过指定时间 long 之后它会自动唤醒,拥有去争夺锁的资格。
102+
不同的地方是,有参方法 `wait(long)` 就算其他线程不来唤醒它,经过指定时间 long 之后它会自动唤醒,拥有去争夺锁的资格。
103103

104-
##### Thread.join(long)
104+
##### `Thread.join(long)`
105105

106-
join(long) 使当前线程执行指定时间,并且使线程进入 TIMED_WAITING 状态。
106+
`join(long)` 使当前线程执行指定时间,并且使线程进入 TIMED_WAITING 状态。
107107

108108
#### 线程中断
109109

110110
简单介绍下 Thread 类里提供的关于线程中断的几个方法:
111111

112-
- Thread.interrupt():中断线程。这里的中断线程并不会立即停止线程,而是设置线程的中断状态为 true(默认是 flase);
113-
- Thread.interrupted():测试当前线程是否被中断。线程的中断状态受这个方法的影响,意思是调用一次使线程中断状态设置为 true,连续调用两次会使得这个线程的中断状态重新转为 false;
114-
- Thread.isInterrupted():测试当前线程是否被中断。与上面方法不同的是调用这个方法并不会影响线程的中断状态。
112+
- `Thread.interrupt()`:中断线程。这里的中断线程并不会立即停止线程,而是设置线程的中断状态为 true(默认是 flase);
113+
- `Thread.interrupted()`:测试当前线程是否被中断。线程的中断状态受这个方法的影响,意思是调用一次使线程中断状态设置为 true,连续调用两次会使得这个线程的中断状态重新转为 false;
114+
- `Thread.isInterrupted()`:测试当前线程是否被中断。与上面方法不同的是调用这个方法并不会影响线程的中断状态。
115115

116116
> 在线程中断机制里,当其他线程通知需要被中断的线程后,线程中断的状态被设置为 true,但是具体被要求中断的线程要怎么处理,完全由被中断线程自己而定,可以在合适的实际处理中断请求,也可以完全不处理继续执行下去。

RedSpiderConcurrent/5.Java 线程间的通信.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
### 等待、通知机制
66

7-
Java 多线程的等待/通知机制是基于 Object 类的 wait() 方法和 notify()notifyAll() 方法来实现的。需要注意的是等待、通知机制使用的是使用同一个对象锁,如果两个线程使用的是不同的对象锁,那它们之间是不能用等待/通知机制通信的。
7+
Java 多线程的等待/通知机制是基于 Object 类的 `wait()` 方法和 `notify()``notifyAll()` 方法来实现的。需要注意的是等待、通知机制使用的是使用同一个对象锁,如果两个线程使用的是不同的对象锁,那它们之间是不能用等待/通知机制通信的。
88

99
### 信号量
1010

@@ -83,18 +83,18 @@ test
8383
可以简单分析一下这个示例代码的执行流程:
8484

8585
1. 线程 ReaderThread 开始执行,
86-
2. 线程 ReaderThread 使用管道 reader.read() 进入”阻塞“,
86+
2. 线程 ReaderThread 使用管道 `reader.read()` 进入”阻塞“,
8787
3. 线程 WriterThread 开始执行,
88-
4. 线程 WriterThread 用 writer.write("test") 往管道写入字符串,
89-
5. 线程 WriterThread 使用 writer.close() 结束管道写入,并执行完毕,
88+
4. 线程 WriterThread 用 `writer.write("test")` 往管道写入字符串,
89+
5. 线程 WriterThread 使用 `writer.close()` 结束管道写入,并执行完毕,
9090
6. 线程 ReaderThread 接受到管道输出的字符串并打印,
9191
7. 线程 ReaderThread 执行完毕。
9292

9393
### 其他通信相关
9494

9595
#### join 方法
9696

97-
join() 方法是 Thread 类的一个实例方法。它的作用是让当前线程陷入“等待”状态,等 join 的这个线程执行完成后,再继续执行当前线程。
97+
`join()` 方法是 Thread 类的一个实例方法。它的作用是让当前线程陷入“等待”状态,等 join 的这个线程执行完成后,再继续执行当前线程。
9898

9999
```java
100100
public class Join {
@@ -121,11 +121,11 @@ public class Join {
121121
}
122122
```
123123

124-
> 注意 join() 方法有两个重载方法,一个是 join(long), 一个是 join(long, int)。
124+
> 注意 `join()` 方法有两个重载方法,一个是 `join(long)`, 一个是 `join(long, int)`
125125
>
126-
> 实际上,通过源码会发现,join() 方法及其重载方法底层都是利用了 wait(long) 这个方法。
126+
> 实际上,通过源码会发现,`join()` 方法及其重载方法底层都是利用了 `wait(long)` 这个方法。
127127
>
128-
> 对于 join(long, int),通过查看源码(JDK 1.8)发现,底层并没有精确到纳秒,而是对第二个参数做了简单的判断和处理。
128+
> 对于 `join(long, int)`,通过查看源码(JDK 1.8)发现,底层并没有精确到纳秒,而是对第二个参数做了简单的判断和处理。
129129
130130
### sleep 方法
131131

RedSpiderConcurrent/6.Java 内存模型基础知识.md

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,10 @@
66
- 消息传递并发模型
77
- 共享内存并发模型
88

9-
10-
| 如何通信 | 如何同步
11-
:-:|:-: |:-:
12-
消息传递并发模型 | 线程之间 **没有公共状态**,线程间的通信必须通过发送消息来显示进行通信 | 发送消息天然同步,因为发送消息总是在接收消息之前,因此同步是隐式的
13-
共享内存并发模型 | 线程之间共享程序的公共状态,通过 **写-读内存中的公共状态** 进行隐式通信 | **必须显式指定某段代码需要在线程之间互斥执行**,同步是显式的
9+
| | 如何通信 | 如何同步 |
10+
| :--------------: | :----------------------------------------------------------: | :----------------------------------------------------------: |
11+
| 消息传递并发模型 | 线程之间 **没有公共状态**,线程间的通信必须通过发送消息来显示进行通信 | 发送消息天然同步,因为发送消息总是在接收消息之前,因此同步是隐式的 |
12+
| 共享内存并发模型 | 线程之间共享程序的公共状态,通过 **写-读内存中的公共状态** 进行隐式通信 | **必须显式指定某段代码需要在线程之间互斥执行**,同步是显式的 |
1413

1514
**在 Java 中,使用的是共享内存并发模型**
1615

@@ -22,7 +21,7 @@
2221
这是因为现代计算机为了高效,往往会在高速缓存区中缓存共享变量,因为 CPU 访问缓存区比访问内存要快得多。
2322
> 线程之间的共享变量存在主内存中,每个线程都有一个私有的本地内存,存储了该线程以读、写共享变量的副本。本地内存是 Java 内存模型的一个抽象概念,并不真实存在。它涵盖了缓存、写缓冲区、寄存器等。
2423
25-
![](http://concurrent.redspider.group/article/02/imgs/JMM%E6%8A%BD%E8%B1%A1%E7%A4%BA%E6%84%8F%E5%9B%BE.jpg)
24+
![](img/JMM抽象示意图.jpg)
2625

2726
线程 A 无法直接访问线程 B 的工作内存,线程间通信必须经过主内存。
2827

0 commit comments

Comments
 (0)