Skip to content

Commit dc90487

Browse files
committed
勘误
1 parent ccf2130 commit dc90487

File tree

4 files changed

+35
-31
lines changed

4 files changed

+35
-31
lines changed

docs/java/jvm/Java内存区域.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ Java 方法有两种返回方式:
123123

124124
本地方法被执行的时候,在本地方法栈也会创建一个栈帧,用于存放该本地方法的局部变量表、操作数栈、动态链接、出口信息。
125125

126-
方法执行完毕后相应的栈帧也会出栈并释放内存空间,也会出现 StackOverFlowError 和 OutOfMemoryError 两种错误。
126+
方法执行完毕后相应的栈帧也会出栈并释放内存空间,也会出现 `StackOverFlowError``OutOfMemoryError` 两种错误。
127127

128128
### 2.4 堆
129129

@@ -304,7 +304,9 @@ JDK1.4 中新加入的 **NIO(New Input/Output) 类**,引入了一种基于**
304304
### 3.3 对象的访问定位
305305
建立对象就是为了使用对象,我们的 Java 程序通过栈上的 reference 数据来操作堆上的具体对象。对象的访问方式由虚拟机实现而定,目前主流的访问方式有**①使用句柄****②直接指针**两种:
306306
307-
1. **句柄:** 如果使用句柄的话,那么 Java 堆中将会划分出一块内存来作为句柄池,reference 中存储的就是对象的句柄地址,而句柄中包含了对象实例数据与类型数据各自的具体地址信息; ![对象的访问定位-使用句柄](./pictures/java内存区域/对象的访问定位-使用句柄.png)
307+
1. **句柄:** 如果使用句柄的话,那么 Java 堆中将会划分出一块内存来作为句柄池,reference 中存储的就是对象的句柄地址,而句柄中包含了对象实例数据与类型数据各自的具体地址信息;
308+
309+
![对象的访问定位-使用句柄](./pictures/java内存区域/对象的访问定位-使用句柄.png)
308310
309311
2. **直接指针:** 如果使用直接指针访问,那么 Java 堆对象的布局中就必须考虑如何放置访问类型数据的相关信息,而 reference 中存储的直接就是对象的地址。
310312

docs/java/multi-thread/2020最新Java并发基础常见面试题总结.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -279,18 +279,18 @@ Process finished with exit code 0
279279

280280
## 9. 说说 sleep() 方法和 wait() 方法区别和共同点?
281281

282-
- 两者最主要的区别在于:**sleep 方法没有释放锁,而 wait 方法释放了锁**
282+
- 两者最主要的区别在于:**`sleep()` 方法没有释放锁,而 `wait()` 方法释放了锁**
283283
- 两者都可以暂停线程的执行。
284-
- Wait 通常被用于线程间交互/通信,sleep 通常被用于暂停执行。
285-
- wait() 方法被调用后,线程不会自动苏醒,需要别的线程调用同一个对象上的 notify() 或者 notifyAll() 方法。sleep() 方法执行完成后,线程会自动苏醒。或者可以使用 wait(long timeout)超时后线程会自动苏醒。
284+
- `wait()` 通常被用于线程间交互/通信,`sleep() `通常被用于暂停执行。
285+
- `wait()` 方法被调用后,线程不会自动苏醒,需要别的线程调用同一个对象上的 `notify() `或者 `notifyAll()` 方法。`sleep() `方法执行完成后,线程会自动苏醒。或者可以使用 `wait(long timeout)` 超时后线程会自动苏醒。
286286

287287
## 10. 为什么我们调用 start() 方法时会执行 run() 方法,为什么我们不能直接调用 run() 方法?
288288

289289
这是另一个非常经典的 java 多线程面试问题,而且在面试中会经常被问到。很简单,但是很多人都会答不上来!
290290

291-
new 一个 Thread,线程进入了新建状态;调用 start() 方法,会启动一个线程并使线程进入了就绪状态,当分配到时间片后就可以开始运行了。 start() 会执行线程的相应准备工作,然后自动执行 run() 方法的内容,这是真正的多线程工作。 而直接执行 run() 方法,会把 run 方法当成一个 main 线程下的普通方法去执行,并不会在某个线程中执行它,所以这并不是多线程工作。
291+
new 一个 Thread,线程进入了新建状态调用 `start()`方法,会启动一个线程并使线程进入了就绪状态,当分配到时间片后就可以开始运行了。 `start()` 会执行线程的相应准备工作,然后自动执行 ` run() ` 方法的内容,这是真正的多线程工作。 但是,直接执行 `run()` 方法,会把 `run()` 方法当成一个 main 线程下的普通方法去执行,并不会在某个线程中执行它,所以这并不是多线程工作。
292292

293-
**总结: 调用 start 方法方可启动线程并使线程进入就绪状态,run 方法只是 thread 的一个普通方法调用,还是在主线程里执行**
293+
**总结: 调用 `start()` 方法方可启动线程并使线程进入就绪状态,直接执行 `run()` 方法的话不会以多线程的方式执行**
294294

295295
## 公众号
296296

docs/java/multi-thread/2020最新Java并发进阶常见面试题总结.md

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,9 @@
7474

7575
因为监视器锁(monitor)是依赖于底层的操作系统的 `Mutex Lock` 来实现的,Java 的线程是映射到操作系统的原生线程之上的。如果要挂起或者唤醒一个线程,都需要操作系统帮忙完成,而操作系统实现线程之间的切换时需要从用户态转换到内核态,这个状态之间的转换需要相对比较长的时间,时间成本相对较高。
7676

77-
庆幸的是在 Java 6 之后 Java 官方对从 JVM 层面对 synchronized 较大优化,所以现在的 synchronized 锁效率也优化得很不错了。JDK1.6 对锁的实现引入了大量的优化,如自旋锁、适应性自旋锁、锁消除、锁粗化、偏向锁、轻量级锁等技术来减少锁操作的开销。
77+
庆幸的是在 Java 6 之后 Java 官方对从 JVM 层面对 `synchronized` 较大优化,所以现在的 `synchronized` 锁效率也优化得很不错了。JDK1.6 对锁的实现引入了大量的优化,如自旋锁、适应性自旋锁、锁消除、锁粗化、偏向锁、轻量级锁等技术来减少锁操作的开销。
7878

79-
所以,你会发现目前的话,不论是各种开源框架还是 JDK 源码都大量使用了 synchronized 关键字。
79+
所以,你会发现目前的话,不论是各种开源框架还是 JDK 源码都大量使用了 `synchronized` 关键字。
8080

8181
### 1.2. 说说自己是怎么使用 synchronized 关键字
8282

@@ -296,9 +296,9 @@ JDK1.6 对锁的实现引入了大量的优化,如偏向锁、轻量级锁、
296296

297297
`synchronized` 关键字和 `volatile` 关键字是两个互补的存在,而不是对立的存在!
298298

299-
- **volatile 关键字**是线程同步的**轻量级实现**,所以**volatile 性能肯定比 synchronized 关键字要好**。但是**volatile 关键字只能用于变量而 synchronized 关键字可以修饰方法以及代码块**
300-
- **volatile 关键字能保证数据的可见性,但不能保证数据的原子性。synchronized 关键字两者都能保证。**
301-
- **volatile 关键字主要用于解决变量在多个线程之间的可见性,而 synchronized 关键字解决的是多个线程之间访问资源的同步性。**
299+
- **`volatile` 关键字**是线程同步的**轻量级实现**,所以**`volatile `性能肯定比` synchronized `关键字要好**。但是**`volatile` 关键字只能用于变量而 `synchronized` 关键字可以修饰方法以及代码块**
300+
- **`volatile` 关键字能保证数据的可见性,但不能保证数据的原子性。`synchronized` 关键字两者都能保证。**
301+
- **`volatile`关键字主要用于解决变量在多个线程之间的可见性,而 `synchronized` 关键字解决的是多个线程之间访问资源的同步性。**
302302

303303
## 3. ThreadLocal
304304

@@ -814,7 +814,7 @@ pool-1-thread-1 End. Time = Tue Nov 12 20:59:54 CST 2019
814814

815815
### 5.1. 介绍一下 Atomic 原子类
816816

817-
Atomic 翻译成中文是原子的意思。在化学上,我们知道原子是构成一般物质的最小单位,在化学反应中是不可分割的。在我们这里 Atomic 是指一个操作是不可中断的。即使是在多个线程一起执行的时候,一个操作一旦开始,就不会被其他线程干扰。
817+
`Atomic` 翻译成中文是原子的意思。在化学上,我们知道原子是构成一般物质的最小单位,在化学反应中是不可分割的。在我们这里 Atomic 是指一个操作是不可中断的。即使是在多个线程一起执行的时候,一个操作一旦开始,就不会被其他线程干扰。
818818

819819
所以,所谓原子类说简单点就是具有原子/原子操作特征的类。
820820

@@ -828,29 +828,29 @@ Atomic 翻译成中文是原子的意思。在化学上,我们知道原子是
828828

829829
使用原子的方式更新基本类型
830830

831-
- AtomicInteger:整形原子类
832-
- AtomicLong:长整型原子类
833-
- AtomicBoolean:布尔型原子类
831+
- `AtomicInteger`:整形原子类
832+
- `AtomicLong`:长整型原子类
833+
- `AtomicBoolean`:布尔型原子类
834834

835835
**数组类型**
836836

837837
使用原子的方式更新数组里的某个元素
838838

839-
- AtomicIntegerArray:整形数组原子类
840-
- AtomicLongArray:长整形数组原子类
841-
- AtomicReferenceArray:引用类型数组原子类
839+
- `AtomicIntegerArray`:整形数组原子类
840+
- `AtomicLongArray`:长整形数组原子类
841+
- `AtomicReferenceArray`:引用类型数组原子类
842842

843843
**引用类型**
844844

845-
- AtomicReference:引用类型原子类
846-
- AtomicStampedReference:原子更新带有版本号的引用类型。该类将整数值与引用关联起来,可用于解决原子的更新数据和数据的版本号,可以解决使用 CAS 进行原子更新时可能出现的 ABA 问题。
847-
- AtomicMarkableReference :原子更新带有标记位的引用类型
845+
- `AtomicReference`:引用类型原子类
846+
- `AtomicStampedReference`:原子更新带有版本号的引用类型。该类将整数值与引用关联起来,可用于解决原子的更新数据和数据的版本号,可以解决使用 CAS 进行原子更新时可能出现的 ABA 问题。
847+
- `AtomicMarkableReference` :原子更新带有标记位的引用类型
848848

849849
**对象的属性修改类型**
850850

851-
- AtomicIntegerFieldUpdater:原子更新整形字段的更新器
852-
- AtomicLongFieldUpdater:原子更新长整形字段的更新器
853-
- AtomicReferenceFieldUpdater:原子更新引用类型字段的更新器
851+
- `AtomicIntegerFieldUpdater`:原子更新整形字段的更新器
852+
- `AtomicLongFieldUpdater`:原子更新长整形字段的更新器
853+
- `AtomicReferenceFieldUpdater`:原子更新引用类型字段的更新器
854854

855855
### 5.3. 讲讲 AtomicInteger 的使用
856856

@@ -916,11 +916,11 @@ CAS 的原理是拿期望的值和原本的一个值作比较,如果相同则
916916

917917
### 6.1. AQS 介绍
918918

919-
AQS 的全称为(AbstractQueuedSynchronizer),这个类在 java.util.concurrent.locks 包下面。
919+
AQS 的全称为(`AbstractQueuedSynchronizer`),这个类在` java.util.concurrent.locks `包下面。
920920

921921
![AQS类](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-6/AQS类.png)
922922

923-
AQS 是一个用来构建锁和同步器的框架,使用 AQS 能简单且高效地构造出应用广泛的大量的同步器,比如我们提到的 ReentrantLockSemaphore,其他的诸如 ReentrantReadWriteLockSynchronousQueueFutureTask 等等皆是基于 AQS 的。当然,我们自己也能利用 AQS 非常轻松容易地构造出符合我们自己需求的同步器。
923+
AQS 是一个用来构建锁和同步器的框架,使用 AQS 能简单且高效地构造出应用广泛的大量的同步器,比如我们提到的 `ReentrantLock``Semaphore`,其他的诸如 `ReentrantReadWriteLock``SynchronousQueue``FutureTask` 等等皆是基于 AQS 的。当然,我们自己也能利用 AQS 非常轻松容易地构造出符合我们自己需求的同步器。
924924

925925
### 6.2. AQS 原理分析
926926

@@ -1012,9 +1012,9 @@ tryReleaseShared(int)//共享方式。尝试释放资源,成功则返回true
10121012

10131013
### 6.3. AQS 组件总结
10141014

1015-
- **Semaphore(信号量)-允许多个线程同时访问:** synchronized 和 ReentrantLock 都是一次只允许一个线程访问某个资源,Semaphore(信号量)可以指定多个线程同时访问某个资源。
1016-
- **CountDownLatch (倒计时器):** CountDownLatch 是一个同步工具类,用来协调多个线程之间的同步。这个工具通常用来控制线程等待,它可以让某一个线程等待直到倒计时结束,再开始执行。
1017-
- **CyclicBarrier(循环栅栏):** CyclicBarrier 和 CountDownLatch 非常类似,它也可以实现线程间的技术等待,但是它的功能比 CountDownLatch 更加复杂和强大。主要应用场景和 CountDownLatch 类似。CyclicBarrier 的字面意思是可循环使用(Cyclic)的屏障(Barrier)。它要做的事情是,让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活。CyclicBarrier 默认的构造方法是 CyclicBarrier(int parties),其参数表示屏障拦截的线程数量,每个线程调用 await()方法告诉 CyclicBarrier 我已经到达了屏障,然后当前线程被阻塞。
1015+
- **`Semaphore`(信号量)-允许多个线程同时访问:** `synchronized``ReentrantLock` 都是一次只允许一个线程访问某个资源,`Semaphore`(信号量)可以指定多个线程同时访问某个资源。
1016+
- **`CountDownLatch `(倒计时器):** `CountDownLatch` 是一个同步工具类,用来协调多个线程之间的同步。这个工具通常用来控制线程等待,它可以让某一个线程等待直到倒计时结束,再开始执行。
1017+
- **`CyclicBarrier`(循环栅栏):** `CyclicBarrier``CountDownLatch` 非常类似,它也可以实现线程间的技术等待,但是它的功能比 `CountDownLatch` 更加复杂和强大。主要应用场景和 `CountDownLatch` 类似。`CyclicBarrier` 的字面意思是可循环使用(`Cyclic`)的屏障(`Barrier`)。它要做的事情是,让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活。`CyclicBarrier` 默认的构造方法是 `CyclicBarrier(int parties)`,其参数表示屏障拦截的线程数量,每个线程调用 `await()` 方法告诉 `CyclicBarrier` 我已经到达了屏障,然后当前线程被阻塞。
10181018

10191019
### 6.4. 用过 CountDownLatch 么?什么场景下用的?
10201020

docs/operating-system/basis.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,9 @@
271271

272272
### 4.3 虚拟存储器
273273

274-
👨‍💻**面试官** :都说了虚拟内存了。你再讲讲**虚拟存储器**把!
274+
> **勘误:虚拟存储器又叫做虚拟内存,都是 Virtual Memory 的翻译,属于同一个概念。**
275+
276+
👨‍💻**面试官**~~都说了虚拟内存了。你再讲讲**虚拟存储器**把!~~
275277

276278
🙋 ****
277279

0 commit comments

Comments
 (0)