seamew 1 anno fa
parent
commit
a4d4c7c21f

+ 78 - 61
Git学习笔记/git与vim常见指令集.md

@@ -2,6 +2,7 @@
 
 # 常用Git命令总结
 
+```shell
 - git config --global user.name "你的名字" 让你全部的Git仓库绑定你的名字
 - git config --global user.email "你的邮箱" 让你全部的Git仓库绑定你的邮箱
 - git init 初始化你的仓库
@@ -48,6 +49,9 @@
 - git config --global color.ui true 让Git显示颜色,会让命令输出看起来更醒目
 - git add -f <file> 强制提交已忽略的的文件
 - git check-ignore -v <file> 检查为什么Git会忽略该文件
+```
+
+
 
 
 
@@ -55,78 +59,37 @@
 
 ## VIM 进入和退出命令
 
-> 常用命令是ESC,然后:wq(保存并退出),:q!(不保存并强制退出),i进入vim模式。另外还有其它的,我可能都不会用到。。。
-> 按ESC键 跳到命令模式,然后:
+> **常用命令是ESC,然后:wq(保存并退出),:q!(不保存并强制退出),i进入vim模式。另外还有其它的,我可能都不会用到。。。**
+> **按ESC键 跳到命令模式,然后:**
 
-1. **:w 保存文件但不退出vi**
-2. **:w file 将修改另外保存到file中,不退出vi**
-3. **:w! 强制保存,不推出vi**
-4. **:wq 保存文件并退出vi**
-5. **:wq! 强制保存文件,并退出vi**
-6. **q: 不保存文件,退出vi**
-7. **:q! 不保存文件,强制退出vi**
-8. **:e! 放弃所有修改,从上次保存文件开始再编辑**
+```shell
+1. :w 保存文件但不退出vi
+2. :w file 将修改另外保存到file中,不退出vi
+3. :w! 强制保存,不推出vi
+4. :wq 保存文件并退出vi
+5. :wq! 强制保存文件,并退出vi
+6. q: 不保存文件,退出vi
+7. :q! 不保存文件,强制退出vi
+8. :e! 放弃所有修改,从上次保存文件开始再编辑
+```
 
 ## 命令历史
 
+```shell
 以:和/开头的命令都有历史纪录,可以首先键入:或/然后按上下箭头来选择某个历史命令。
-
-## 启动vim
-
-在命令行窗口中输入以下命令即可
-
-vim 直接启动vim
-
-vim filename 打开vim并创建名为filename的文件
-
-## 文件命令
-
-打开单个文件
-
-vim file
-
-同时打开多个文件
-
-vim file1 file2 file3 ...
-
-在vim窗口中打开一个新文件
-
-:open file
-
-在新窗口中打开文件
-
-:split file
-
-切换到下一个文件
-
-:bn
-
-切换到上一个文件
-
-:bp
-
-查看当前打开的文件列表,当前正在编辑的文件会用[]括起来。
-
-:args
-
-打开远程文件,比如ftp或者share folder
-
-:e ftp://192.168.10.76/abc.txt
-
-:e \\qadrive\test\1.txt
-
-## vim的模式
-
-正常模式(按Esc或Ctrl+[进入) 左下角显示文件名或为空
-插入模式(按i键进入) 左下角显示--INSERT--
-可视模式(不知道如何进入) 左下角显示--VISUAL--
+```
 
 ## 导航命令
 
+```shell
 % 括号匹配
+```
+
+
 
 ## 插入命令
 
+```shell
 i 在当前位置生前插入
 
 I 在当前行首插入
@@ -138,9 +101,13 @@ A 在当前行尾插入
 o 在当前行之后插入一行
 
 O 在当前行之前插入一行
+```
+
+
 
 ## 查找命令
 
+```shell
 /text  查找text,按n健查找下一个,按N健查找前一个。
 
 ?text  查找text,反向查找,按n健查找下一个,按N健查找前一个。
@@ -162,9 +129,13 @@ vim中有一些特殊字符在查找时需要转义  .*[]^%/?~$
 :set incsearch  逐步搜索模式,对当前键入的字符进行搜索而不必等待键入完成。
 
 :set wrapscan  重新搜索,在搜索到文件头或尾时,返回继续搜索,默认开启。
+```
+
+
 
 ## 替换命令
 
+```shell
 ra 将当前字符替换为a,当期字符即光标所在字符。
 
 s/old/new/ 用old替换new,替换当前行的第一个匹配
@@ -178,9 +149,13 @@ s/old/new/g 用old替换new,替换当前行的所有匹配
 :10,20 s/^/  /g 在第10行知第20行每行前面加四个空格,用于缩进。
 
 ddp 交换光标所在行和其下紧邻的一行。
+```
+
+
 
 ## 移动命令
 
+```shell
 h 左移一个字符
 l 右移一个字符,这个命令很少用,一般用w代替。
 k 上移一个字符
@@ -224,15 +199,23 @@ Ctrl + u 向上滚动半屏
 Ctrl + f 向下滚动一屏
 
 Ctrl + b 向上滚动一屏
+```
+
+
 
 ## 撤销和重做
 
+```shell
 u 撤销(Undo)
 U 撤销对整行的操作
 Ctrl + r 重做(Redo),即撤销的撤销。
+```
+
+
 
 ## 删除命令
 
+```shell
 x 删除当前字符
 
 3x 删除当前光标开始向后三个字符
@@ -266,9 +249,13 @@ jdG(jd shift + g)  删除当前行之后所有行(不包括当前行)
 :1,$d 删除所有行
 
 J(shift + j)  删除两行之间的空行,实际上是合并两行。
+```
+
+
 
 ## 拷贝和粘贴
 
+```shell
 yy 拷贝当前行
 
 nyy 拷贝当前后开始的n行,比如2yy拷贝当前行及其下一行。
@@ -286,9 +273,13 @@ shift+p 在当前行前粘贴
 ddp交换当前行和其下一行
 
 xp交换当前字符和其后一个字符
+```
+
+
 
 ## 剪切命令
 
+```shell
 正常模式下按v(逐字)或V(逐行)进入可视模式,然后用jklh命令移动即可选择某些行或字符,再按d即可剪切
 
 ndd 剪切当前行之后的n行。利用p命令可以对剪切的内容进行粘贴
@@ -296,9 +287,13 @@ ndd 剪切当前行之后的n行。利用p命令可以对剪切的内容进行
 :1,10d 将1-10行剪切。利用p命令可将剪切后的内容进行粘贴。
 
 :1, 10 m 20 将第1-10行移动到第20行之后。
+```
+
+
 
 ## 退出命令
 
+```shell
 :wq 保存并退出
 
 ZZ 保存并退出
@@ -306,9 +301,13 @@ ZZ 保存并退出
 :q! 强制退出并忽略所有更改
 
 :e! 放弃所有修改,并打开原来文件。
+```
+
+
 
 ## 窗口命令
 
+```shell
 :split或new 打开一个新窗口,光标停在顶层的窗口上
 
 :split file或:new file 用新窗口打开文件
@@ -336,9 +335,13 @@ ZZ 保存并退出。
 录制宏
 
 按q键加任意字母开始录制,再按q键结束录制(这意味着vim中的宏不可嵌套),使用的时候@加宏名,比如qa。。。q录制名为a的宏,@a使用这个宏。
+```
+
+
 
 ## 执行shell命令
 
+```shell
 :!command
 
 :!ls 列出当前目录下文件
@@ -348,9 +351,13 @@ ZZ 保存并退出。
 :!perl script.pl 执行perl脚本,可以不用退出vim,非常方便。
 
 :suspend或Ctrl - Z 挂起vim,回到shell,按fg可以返回vim。
+```
+
+
 
 ## 注释命令
 
+```shell
 perl程序中#开始的行为注释,所以要注释某些行,只需在行首加入#
 
 3,5 s/^/#/g 注释第3-5行
@@ -360,9 +367,13 @@ perl程序中#开始的行为注释,所以要注释某些行,只需在行首
 1,$ s/^/#/g 注释整个文档。
 
 :%s/^/#/g 注释整个文档,此法更快。
+```
+
+
 
 ## 帮助命令
 
+```shell
 :help or F1 显示整个帮助
 :help xxx 显示xxx的帮助,比如 :help i, :help CTRL-[(即Ctrl+[的帮助)。
 :help 'number' Vim选项的帮助用单引号括起
@@ -370,9 +381,13 @@ perl程序中#开始的行为注释,所以要注释某些行,只需在行首
 :help -t Vim启动参数的帮助用-
 :help i_<Esc> 插入模式下Esc的帮助,某个模式下的帮助用模式_主题的模式
 帮助文件中位于||之间的内容是超链接,可以用Ctrl+]进入链接,Ctrl+o(Ctrl + t)返回
+```
+
+
 
 ## 其他非编辑命令
 
+```shell
 . 重复前一次命令
 
 :set ruler?  查看是否设置了ruler,在.vimrc中,使用set命令设制的选项都可以通过这个命令查看
@@ -390,4 +405,6 @@ $ vimtutor
 :syntax 列出已经定义的语法项
 :syntax clear 清除已定义的语法规则
 :syntax case match 大小写敏感,int和Int将视为不同的语法元素
-:syntax case ignore 大小写无关,int和Int将视为相同的语法元素,并使用同样的配色方案
+:syntax case ignore 大小写无关,int和Int将视为相同的语法元素,并使用同样的配色方案
+```
+

+ 17 - 280
Git学习笔记/你可能会忽略的 Git 提交规范摘录.md

@@ -1,289 +1,26 @@
-# #目录
-
->[TOC]
-
 # 本人笔记提交标准
 
-```jsx
-docs: 新建知识点笔记
-feat:新增知识点(feature)。
-update:对于某部分知识点的更新修改(不是勘误,如更新目录索引、某正确知识点补全等操作)
-fix:勘误,修正知识点错误等操作
-style:如文档内样式调整,格式调整等不影响笔记内容的操作 (如删除多余资源,如无用的图片,无用语句删除等)
-refactor:笔记重构与优化(主要就是目录变动、笔记文件结构调整、文件名更改等操作)
-//举例
-docs(算法):新建数据结构与算法知识点笔记
-feat(前端-promise): 新增笔记中async+await+promise知识点笔记
-fix(前端-微信小程序):更正笔记中对于自定义组件描述的不恰当处
-refactor(前端):对于前端笔记部分文件目录进行重构调整
-style(后台-java):进行对该笔记中笔记格式与样式调整 或 进行对该笔记中多余图片展示资源的删除
-update:(README):笔记目录索引更新-新增小程序自封装组件笔记索引
-```
-
-
-
-# 你可能会忽略的 Git 提交规范
-
-一直是 ESLint 的忠实用户,深知规范的重要性。然而,在新项目交接中,我被 Git Commit 规范逼疯了。才意识到自己的疏忽,于是便有了一探究竟的想法。
-
-#### 一、为什么需要规范?
-
-无规矩不成方圆,编程也一样。
-
-如果你有一个项目,从始至终都是自己写,那么你想怎么写都可以,没有人可以干预你。可是如果在团队协作中,大家都张扬个性,那么代码将会是一团糟,好好的项目就被糟践了。不管是开发还是日后维护,都将是灾难。
-
-这时候,有人提出了何不统一标准,大家都按照这个标准来。于是 `ESLint`,`JSHint` 等代码工具如雨后春笋般涌现,成为了项目构建的必备良品。
-
-`Git Commit` 规范可能并没有那么夸张,但如果你在版本回退的时候看到一大段糟心的 `Commit`,恐怕会懊恼不已吧。所以,严格遵守规范,利人利己。
-
-#### 二、具体规则
-
-先来看看公式:
-
-```
-<type>(<scope>): <subject>
-```
-
-
-
-- type
-
-  - 用于说明
-
-     
-
-    ```
-    commit
-    ```
-
-     
-
-    的类别,只允许使用下面7个标识。
-
-    ```jsx
-    feat:新功能(feature)。
-    fix/to:修复bug,可以是QA发现的BUG,也可以是研发自己发现的BUG。
-    fix:产生diff并自动修复此问题。适合于一次提交直接修复问题
-    to:只产生diff不自动修复此问题。适合于多次提交。最终修复问题提交时使用fix
-    docs:文档(documentation)。
-    style:格式(不影响代码运行的变动)。
-    refactor:重构(即不是新增功能,也不是修改bug的代码变动)。
-    perf:优化相关,比如提升性能、体验。
-    test:增加测试。
-    chore:构建过程或辅助工具的变动。
-    revert:回滚到上一个版本。
-    merge:代码合并。
-    sync:同步主线或分支的Bug。
-    ```
-
-- scope
-
-  - 用于说明 `commit` 影响的范围,比如数据层、控制层、视图层等等,视项目不同而不同。
-
-- subject
-
-  - 是
-
-     
-
-    ```
-    commit
-    ```
-
-     
-
-    目的的简短描述,不超过50个字符。
-
-    ```
-    1.以动词开头,使用第一人称现在时,比如change,而不是changed或changes
-    2.第一个字母小写
-    3.结尾不加句号(.)
-    ```
-
-规范参考自阮一峰老师的文章:[Commit message 和 Change log 编写指南](http://www.ruanyifeng.com/blog/2016/01/commit_message_change_log.html)。
-
-#### 三、异常处理
-
-我们先来看看这个异常提醒:
-
-```
-INVALID COMMIT MSG: does not match "<type>(<scope>): <subject>" !
-jartto:fix bug
-```
-
-
-
-这里之所以报出这个警告,是因为我的提交出现了两个问题:
-其一,使用了规范外的关键字;
-其二,很细节的问题,jartto:后少了空格;
-
-这时候我才回忆起来,当时提交一直失败,情急之下直接强制提交,所以以后的提交都会抱出这个异常。大致意思就是:
-
-你的之前的 Commit 不合格~你的之前的 Commit 不合格~你的之前的 Commit 不合格
-
-这时候就很烦了,我们只能去将之前的错误修正,那么如何操作呢?
-
-#### 四、如何修改之前的 commit 信息?
-
-其实并不复杂,我们只需要这样做:
-1、将当前分支无关的工作状态进行暂存
-
-```
-git stash
-```
-
-
-
-2、将 `HEAD` 移动到需要修改的 `commit` 上
-
-```
-git rebase 9633cf0919^ --interactive
-```
-
+**分支命名**:日期_姓名首字母缩写_功能单词,如:`210804_xfg_buildFramework`
 
+**提交规范**:`作者,type: desc` 如:`孙浩博,fix:修复查询用户信息逻辑问题` *参考Commit message 规范*
 
-3、找到需要修改的 `commit` ,将首行的 `pick` 改成 `edit`
-4、开始着手解决你的 `bug`
-5、 `git add` 将改动文件添加到暂存
-6、 `git commit –amend` 追加改动到提交
-7、`git rebase –continue` 移动 `HEAD` 回最新的 `commit`
-8、恢复之前的工作状态
-
-```
-git stash pop
-```
-
-
-
-大功告成,是不是想把整个 Commit 都修改一遍,逃~
-
-此处参考自:[修改 Commit 日志和内容](https://www.aliyun.com/jiaocheng/125261.html)
-
-#### 五、项目中使用
-
-这时候问题又来了,为什么我提交的时候会有警告,这个又是如何做到的呢?
-
-这时候,我们需要一款 `Node` 插件 `validate-commit-msg` 来检查项目中 `Commit message` 是否规范。
-
-1.首先,安装插件:
-
-```
-npm install --save-dev validate-commit-msg
-```
-
+```shell
+# 主要type
+feat:     增加新功能
+fix:      修复bug
 
+# 特殊type
+docs:     只改动了文档相关的内容
+style:    不影响代码含义的改动,例如去掉空格、改变缩进、增删分号
+build:    构造工具的或者外部依赖的改动,例如webpack,npm
+refactor: 代码重构时使用
+revert:   执行git revert打印的message
 
-2.使用方式一,建立 `.vcmrc` 文件:
-
-```
-{
-  "types": ["feat", "fix", "docs", "style", "refactor", "perf", "test", "build", "ci", "chore", "revert"],
-  "scope": {
-    "required": false,
-    "allowed": ["*"],
-    "validate": false,
-    "multiple": false
-  },
-  "warnOnFail": false,
-  "maxSubjectLength": 100,
-  "subjectPattern": ".+",
-  "subjectPatternErrorMsg": "subject does not match subject pattern!",
-  "helpMessage": "",
-  "autoFix": false
-}
-```
-
-
-
-3.使用方式二:写入 `package.json`
-
-```
-{
-  "config": {
-    "validate-commit-msg": {
-      /* your config here */
-    }
-  }
-}
+# 暂不使用type
+test:     添加测试或者修改现有测试
+perf:     提高性能的改动
+ci:       与CI(持续集成服务)有关的改动
+chore:    不修改src或者test的其余修改,例如构建过程或辅助工具的变动
 ```
 
 
-
-4.可是我们如果想自动使用 [`ghooks`](https://www.npmjs.com/package/ghooks) 钩子函数呢?
-
-```
-{
-  …
-  "config": {
-    "ghooks": {
-      "pre-commit": "gulp lint",
-      "commit-msg": "validate-commit-msg",
-      "pre-push": "make test",
-      "post-merge": "npm install",
-      "post-rewrite": "npm install",
-      …
-    }
-  }
-  …
-}
-```
-
-
-
-在 `ghooks` 中我们可以做很多事情,当然不只是 `validate-commit-msg` 哦。
-
-更多细节请参考:[validate-commit-msg](https://github.com/conventional-changelog-archived-repos/validate-commit-msg)
-
-#### 六、Commit 规范的作用
-
-1.提供更多的信息,方便排查与回退;
-2.过滤关键字,迅速定位;
-3.方便生成文档;
-
-#### 七、生成 Change log
-
-正如[上文](http://jartto.wang/2018/07/08/git-commit/)提到的生成文档,如果我们的提交都按照规范的话,那就很简单了。生成的文档包括以下三个部分:
-
-- New features
-- Bug fixes
-- Breaking changes.
-
-每个部分都会罗列相关的 `commit` ,并且有指向这些 `commit` 的链接。当然,生成的文档允许手动修改,所以发布前,你还可以添加其他内容。
-
-这里需要使用工具 [Conventional Changelog](https://github.com/conventional-changelog/conventional-changelog) 生成 `Change log` :
-
-```
-npm install -g conventional-changelog
-cd jartto-domo
-conventional-changelog -p angular -i CHANGELOG.md -w
-```
-
-
-
-为了方便使用,可以将其写入 `package.json` 的 `scripts` 字段。
-
-```
-{
-  "scripts": {
-    "changelog": "conventional-changelog -p angular -i CHANGELOG.md -w -r 0"
-  }
-}
-```
-
-
-
-这样,使用起来就很简单了:
-
-```
-npm run changelog
-```
-
-
-
-到这里,我们所有的问题都搞明白了,🍻Cheers~
-
-#### 八、总结
-
-看完文章,你还会如此放荡不羁吗?你还会随心所欲的编写 `Commit` 吗?你还会如此 `git commit -m "hello jartto"`提交吗?
-
-答案是否定的,因为使用了钩子函数,你没有机会了,否则将是无穷无尽的恢复 `Commit`。这倒可以养成良好的提交习惯,🙈~

+ 0 - 25
Git学习笔记/开发规范.md

@@ -1,25 +0,0 @@
-### 开发规范
-
-**分支命名**:日期_姓名首字母缩写_功能单词,如:`220804_shb_redisCache`
-
-**提交规范**:`作者,type: desc` 如:`seamew,feat:增加redis缓存` *参考Commit message 规范*
-
-```
-# 主要type
-feat:     增加新功能
-fix:      修复bug
-
-# 特殊type
-docs:     只改动了文档相关的内容
-style:    不影响代码含义的改动,例如去掉空格、改变缩进、增删分号
-build:    构造工具的或者外部依赖的改动,例如webpack,npm
-refactor: 代码重构时使用
-revert:   执行git revert打印的message
-
-# 暂不使用type
-test:     添加测试或者修改现有测试
-perf:     提高性能的改动
-ci:       与CI(持续集成服务)有关的改动
-chore:    不修改src或者test的其余修改,例如构建过程或辅助工具的变动
-```
-

+ 4 - 0
算法平台/改进.md

@@ -0,0 +1,4 @@
+1. 数据集,目前只有csv文件可以输入,改进为支持图片,视频,文本。类型文件,并且可以在线打标签。
+2. 使用步骤不直观,过于复杂。
+3. 没有用户引导,用户不知道如何使用。
+4. 和中煤系统耦合过高,菜单需要调整修改。

BIN
面经/问答/assets/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzMxNDU3NjY1,size_16,color_FFFFFF,t_70-16944430862672.png


BIN
面经/问答/assets/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzMxNDU3NjY1,size_16,color_FFFFFF,t_70.png


+ 88 - 2
面经/问答/并发编程.md

@@ -85,6 +85,8 @@ AQS提供了一种通用的框架,用于实现线程间的协作和同步操
 
 ![image-20230506170616683](assets/image-20230506170616683.png)
 
+![img](assets/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzMxNDU3NjY1,size_16,color_FFFFFF,t_70.png)
+
 * LockSupport
 
 基于C语言底层实现,它可以阻塞线程以等待许可证,或者取消线程的阻塞状态,而不需要使用传统的synchronized关键字或Object.wait()/notify()方法。
@@ -98,11 +100,95 @@ AQS提供了一种通用的框架,用于实现线程间的协作和同步操
 ## LockSupport和synchronized的区别
 
 * LockSupport不需要获取锁对象,因此避免了可能出现的死锁问题。
-
 * notify只能随机释放一个线程,并不能指定某个特定线程,notifyAll是释放锁对象中的所有线程。而unpark方法可以唤醒指定的线程。
-
 * LockSupport可以先执行unpark()方法,然后再执行park()方法,而Object.notify()方法必须在对应的wait()方法之前执行。
 
+## AQS的共享模式
+
+AQS中,共享模式获取锁的顶层入口方法是`acquireShared`,该方法会获取指定数量的资源,成功的话就直接返回,失败的话就进入等待队列,直到获取资源,
+
+```java
+public final void acquireShared(int arg) {
+ if (tryAcquireShared(arg) < 0)
+  doAcquireShared(arg);
+}
+```
+
+该方法里包含了两个方法的调用,
+
+* tryAcquireShared:尝试获取一定资源的锁,返回的值代表获取锁的状态。
+
+* doAcquireShared:进入等待队列,并循环尝试获取锁,直到成功。
+
+> tryAcquireShared
+>
+> `tryAcquireShared`在AQS里没有实现,同样由自定义的同步器去完成具体的逻辑,像一些较为常见的并发工具Semaphore、CountDownLatch里就有对该方法的自定义实现,虽然实现的逻辑不同,但方法的作用是一样的,就是获取一定资源的资源,然后根据返回值判断是否还有剩余资源,从而决定下一步的操作。
+
+返回值有三种定义:
+
+- 负值代表获取失败;
+- 0代表获取成功,但没有剩余的资源,也就是state已经为0;
+- 正值代表获取成功,而且state还有剩余,其他线程可以继续领取
+
+当返回值小于0时,证明此次获取一定数量的锁失败了,然后就会走`doAcquireShared`方法
+
+* doAcquireShared: 此方法的作用是将当前线程加入等待队列尾部休息,直到其他线程释放资源唤醒自己,自己成功拿到相应量的资源后才返回,这是它的源码:
+
+```java
+private void doAcquireShared(int arg) {
+ // 加入队列尾部
+ final Node node = addWaiter(Node.SHARED);
+ boolean failed = true;
+ try {
+  boolean interrupted = false;
+  // CAS自旋
+  for (;;) {
+   final Node p = node.predecessor();
+   // 判断前驱结点是否是head
+   if (p == head) {
+    // 尝试获取一定数量的锁
+    int r = tryAcquireShared(arg);
+    if (r >= 0) {
+     // 获取锁成功,而且还有剩余资源,就设置当前结点为head,并继续唤醒下一个线程
+     setHeadAndPropagate(node, r);
+     // 让前驱结点去掉引用链,方便被GC
+     p.next = null; // help GC
+     if (interrupted)
+      selfInterrupt();
+     failed = false;
+     return;
+    }
+   }
+   // 跟独占模式一样,改前驱结点waitStatus为-1,并且当前线程挂起,等待被唤醒
+   if (shouldParkAfterFailedAcquire(p, node) &&
+    parkAndCheckInterrupt())
+    interrupted = true;
+  }
+ } finally {
+  if (failed)
+   cancelAcquire(node);
+ }
+}
+ 
+private void setHeadAndPropagate(Node node, int propagate) {
+    Node h = head;
+    // head指向自己
+    setHead(node);
+     // 如果还有剩余量,继续唤醒下一个邻居线程
+    if (propagate > 0 || h == null || h.waitStatus < 0) {
+        Node s = node.next;
+        if (s == null || s.isShared())
+            doReleaseShared();
+    }
+}
+```
+
+按照正常的思维,共享模式是可以多个线程同时执行的才对,所以,多个线程的情况下,如果老大释放完资源,但这部分资源满足不了老二,但能满足老三,那么老三就可以拿到资源。可事实是,从源码设计中可以看出,如果真的发生了这种情况,老三是拿不到资源的,因为等待队列是按顺序排列的,老二的资源需求量大,会把后面量小的老三以及老四、老五等都给卡住。**从这一个角度来看,虽然AQS严格保证了顺序,但也降低了并发能力**
+
+## await
+
+![img](assets/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzMxNDU3NjY1,size_16,color_FFFFFF,t_70-16944430862672.png)
+
 ## 线程池
 
 线程池就是管理一系列线程的资源池。当有任务要处理时,直接从线程池中获取线程来处理,处理完之后线程并不会立即被销毁,而是等待下一个任务。线程池的优点和好处主要有以下三点