From 00626f99dd389ef4adb4fe005801795d97d66810 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Mon, 23 Jul 2018 22:34:27 +0800 Subject: [PATCH] auto commit --- README.md | 4 ++-- "notes/Java \345\271\266\345\217\221.md" | 20 ++++++++++------- ...214\207 offer \351\242\230\350\247\243.md" | 13 ++++++++++- ...15\344\275\234\347\263\273\347\273\237.md" | 2 +- ...27\346\234\272\347\275\221\347\273\234.md" | 22 +++++++++---------- 5 files changed, 38 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 5624918d..ce4d69a0 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ | Ⅰ | Ⅱ | Ⅲ | Ⅳ | Ⅴ | Ⅵ | Ⅶ | Ⅷ | Ⅸ | Ⅹ | | :--------: | :---------: | :---------: | :---------: | :---------: | :---------:| :---------: | :-------: | :-------:| :------:| -| 算法[:pencil2:](#算法-pencil2) | 操作系统[:computer:](#操作系统-computer)|网络[:cloud:](#网络-cloud) | 面向对象[:couple:](#面向对象-couple) |数据库[:floppy_disk:](#数据库-floppy_disk)| Java [:coffee:](#java-coffee)| 分布式 [:sweat_drops:](#分布式-sweat_drops)| 工具[:hammer:](#工具-hammer)| 编码实践[:speak_no_evil:](#编码实践-speak_no_evil)| 后记[:memo:](#后记-memo) | +| 算法[:pencil2:](#算法-pencil2) | 操作系统[:computer:](#操作系统-computer)|网络[:cloud:](#网络-cloud) | 面向对象[:couple:](#面向对象-couple) |数据库[:floppy_disk:](#数据库-floppy_disk)| Java [:coffee:](#java-coffee)| 系统设计[:bulb:](#系统设计-bulb)| 工具[:hammer:](#工具-hammer)| 编码实践[:speak_no_evil:](#编码实践-speak_no_evil)| 后记[:memo:](#后记-memo) | ## 算法 :pencil2: @@ -96,7 +96,7 @@ Leetcode 上数据库题目的解题记录。 包含 NIO 的原理以及实例。 -## 分布式 :sweat_drops: +## 系统设计 :bulb: > [一致性](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/一致性.md) diff --git "a/notes/Java \345\271\266\345\217\221.md" "b/notes/Java \345\271\266\345\217\221.md" index 800796db..ab3528f2 100644 --- "a/notes/Java \345\271\266\345\217\221.md" +++ "b/notes/Java \345\271\266\345\217\221.md" @@ -499,7 +499,7 @@ public synchronized static void fun() { ## ReentrantLock -ReentrantLock 是 java.util.concurrent(J.U.C)包中的锁. +ReentrantLock 是 java.util.concurrent(J.U.C)包中的锁。 ```java public class LockExample { @@ -952,7 +952,7 @@ produce..produce..consume..consume..produce..consume..produce..consume..produce. ```java public class ForkJoinExample extends RecursiveTask { - private final int threhold = 5; + private final int threshold = 5; private int first; private int last; @@ -964,7 +964,7 @@ public class ForkJoinExample extends RecursiveTask { @Override protected Integer compute() { int result = 0; - if (last - first <= threhold) { + if (last - first <= threshold) { // 任务足够小则直接计算 for (int i = first; i <= last; i++) { result += i; @@ -1134,7 +1134,7 @@ public static void main(String[] args) throws InterruptedException { 1000 ``` -除了使用原子类之外,也可以使用 synchronized 互斥锁来保证操作的完整性,它对应的内存间交互操作为:lock 和 unlock,在虚拟机实现上对应的字节码指令为 monitorenter 和 monitorexit。 +除了使用原子类之外,也可以使用 synchronized 互斥锁来保证操作的原子性。它对应的内存间交互操作为:lock 和 unlock,在虚拟机实现上对应的字节码指令为 monitorenter 和 monitorexit。 ```java public class AtomicSynchronizedExample { @@ -1176,9 +1176,13 @@ public static void main(String[] args) throws InterruptedException { 可见性指当一个线程修改了共享变量的值,其它线程能够立即得知这个修改。Java 内存模型是通过在变量修改后将新值同步回主内存,在变量读取前从主内存刷新变量值来实现可见性的。 -volatile 可保证可见性。synchronized 也能够保证可见性,对一个变量执行 unlock 操作之前,必须把变量值同步回主内存。final 关键字也能保证可见性:被 final 关键字修饰的字段在构造器中一旦初始化完成,并且没有发生 this 逃逸(其它线程可以通过 this 引用访问到初始化了一半的对象),那么其它线程就能看见 final 字段的值。 +主要有有三种实现可见性的方式: -对前面的线程不安全示例中的 cnt 变量用 volatile 修饰,不能解决线程不安全问题,因为 volatile 并不能保证操作的原子性。 +- volatile +- synchronized,对一个变量执行 unlock 操作之前,必须把变量值同步回主内存。 +- final,被 final 关键字修饰的字段在构造器中一旦初始化完成,并且没有发生 this 逃逸(其它线程通过 this 引用访问到初始化了一半的对象),那么其它线程就能看见 final 字段的值。 + +对前面的线程不安全示例中的 cnt 变量使用 volatile 修饰,不能解决线程不安全问题,因为 volatile 并不能保证操作的原子性。 ### 3. 有序性 @@ -1662,9 +1666,9 @@ JDK 1.6 引入了偏向锁和轻量级锁,从而让锁拥有了四个状态: - 缩小同步范围,例如对于 synchronized,应该尽量使用同步块而不是同步方法。 -- 多用同步类少用 wait() 和 notify()。首先,CountDownLatch, Semaphore, CyclicBarrier 和 Exchanger 这些同步类简化了编码操作,而用 wait() 和 notify() 很难实现对复杂控制流的控制。其次,这些类是由最好的企业编写和维护,在后续的 JDK 中它们还会不断优化和完善,使用这些更高等级的同步工具你的程序可以不费吹灰之力获得优化。 +- 多用同步类少用 wait() 和 notify()。首先,CountDownLatch, CyclicBarrier, Semaphore 和 Exchanger 这些同步类简化了编码操作,而用 wait() 和 notify() 很难实现对复杂的控制流;其次,这些同步类是由最好的企业编写和维护,在后续的 JDK 中还会不断优化和完善,使用这些更高等级的同步工具你的程序可以不费吹灰之力获得优化。 -- 多用并发集合少用同步集合。并发集合比同步集合的可扩展性更好,例如应该使用 ConcurrentHashMap 而不是 Hashtable。 +- 多用并发集合少用同步集合,例如应该使用 ConcurrentHashMap 而不是 Hashtable。 - 使用本地变量和不可变类来保证线程安全。 diff --git "a/notes/\345\211\221\346\214\207 offer \351\242\230\350\247\243.md" "b/notes/\345\211\221\346\214\207 offer \351\242\230\350\247\243.md" index 7ff73846..8fac06b4 100644 --- "a/notes/\345\211\221\346\214\207 offer \351\242\230\350\247\243.md" +++ "b/notes/\345\211\221\346\214\207 offer \351\242\230\350\247\243.md" @@ -613,6 +613,8 @@ public int RectCover(int n) { 因为 h 的赋值表达式为 h = m,因此循环体的循环条件应该为 l < h,详细解释请见 [Leetcode 题解](https://github.com/CyC2018/Interview-Notebook/blob/master/notes/Leetcode%20%E9%A2%98%E8%A7%A3.md#%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE) 二分查找部分。 +但是如果出现 nums[l] == nums[m] == nums[h],那么此时无法确定解在哪个区间,因此需要切换到顺序查找。 + 复杂度:O(logN) + O(1) ```java @@ -622,13 +624,22 @@ public int minNumberInRotateArray(int[] nums) { int l = 0, h = nums.length - 1; while (l < h) { int m = l + (h - l) / 2; - if (nums[m] <= nums[h]) + if (nums[l] == nums[m] && nums[m] == nums[h]) + return minNumber(nums, l, h); + else if (nums[m] <= nums[h]) h = m; else l = m + 1; } return nums[l]; } + +private int minNumber(int[] nums, int l, int h) { + for (int i = l; i < h; i++) + if (nums[i] > nums[i + 1]) + return nums[i + 1]; + return nums[l]; +} ``` # 12. 矩阵中的路径 diff --git "a/notes/\350\256\241\347\256\227\346\234\272\346\223\215\344\275\234\347\263\273\347\273\237.md" "b/notes/\350\256\241\347\256\227\346\234\272\346\223\215\344\275\234\347\263\273\347\273\237.md" index 4a4077d3..52c74dd7 100644 --- "a/notes/\350\256\241\347\256\227\346\234\272\346\223\215\344\275\234\347\263\273\347\273\237.md" +++ "b/notes/\350\256\241\347\256\227\346\234\272\346\223\215\344\275\234\347\263\273\347\273\237.md" @@ -352,7 +352,7 @@ end monitor; 管程引入了 **条件变量** 以及相关的操作:**wait()** 和 **signal()** 来实现同步操作。对条件变量执行 wait() 操作会导致调用进程阻塞,把管程让出来给另一个进程持有。signal() 操作用于唤醒被阻塞的进程。 - **使用管程实现生成者-消费者问题**
+ **使用管程实现生产者-消费者问题**
```pascal // 管程 diff --git "a/notes/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234.md" "b/notes/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234.md" index 8603393c..f1460844 100644 --- "a/notes/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234.md" +++ "b/notes/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234.md" @@ -139,25 +139,17 @@ - **物理层** :考虑的是怎样在传输媒体上传输数据比特流,而不是指具体的传输媒体。物理层的作用是尽可能屏蔽传输媒体和通信手段的差异,使数据链路层感觉不到这些差异。 -### 2. 七层协议 +### 2. OSI 其中表示层和会话层用途如下: -- **表示层** :数据压缩、加密以及数据描述。这使得应用程序不必担心在各台主机中表示/存储的内部格式不同的问题。 +- **表示层** :数据压缩、加密以及数据描述,这使得应用程序不必担心在各台主机中数据内部格式不同的问题。 - **会话层** :建立及管理会话。 五层协议没有表示层和会话层,而是将这些功能留给应用程序开发者处理。 -### 3. 数据在各层之间的传递过程 - -在向下的过程中,需要添加下层协议所需要的首部或者尾部,而在向上的过程中不断拆开首部和尾部。 - -路由器只有下面三层协议,因为路由器位于网络核心中,不需要为进程或者应用程序提供服务,因此也就不需要运输层和应用层。 - -

- -### 4. TCP/IP +### 3. TCP/IP 它只有四层,相当于五层协议中数据链路层和物理层合并为网络接口层。 @@ -169,6 +161,14 @@ TCP/IP 协议族是一种沙漏形状,中间小两边大,IP 协议在其中

+### 4. 数据在各层之间的传递过程 + +在向下的过程中,需要添加下层协议所需要的首部或者尾部,而在向上的过程中不断拆开首部和尾部。 + +路由器只有下面三层协议,因为路由器位于网络核心中,不需要为进程或者应用程序提供服务,因此也就不需要运输层和应用层。 + +

+ # 二、物理层 ## 通信方式 -- GitLab