Skip to content

Commit 5e4788c

Browse files
committed
增加 std::thread 和异常处理的描述
1 parent 3013934 commit 5e4788c

File tree

1 file changed

+24
-1
lines changed

1 file changed

+24
-1
lines changed

md/02使用thread.md

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,30 @@ void f(){
207207

208208
我知道你可能有很多疑问,我们既然 catch 接住了异常,为什么还要 throw?以及为什么我们要两个 join()?
209209

210-
这两个问题其实也算一个问题,如果代码里抛出了异常,就会跳转到 catch 的代码中,执行 join() 确保线程正常执行完成,线程对象可以正常析构。然而此时我们必须再次 throw 抛出异常,因为你要是不抛出,那么你不是还得执行一个 `t.join()`?显然逻辑不对,自然抛出。至于这个**函数产生的异常,由调用方进行处理**,我们只是确保函数 f 中创建的线程正常执行完成,其局部对象正常析构释放。[测试代码](https://godbolt.org/z/jo5sPvPGE)
210+
这两个问题其实也算一个问题,如果代码里抛出了异常,就会跳转到 catch 的代码中,执行 join() 确保线程正常执行完成,线程对象可以正常析构。然而此时我们必须再次 throw 抛出异常,因为你要是不抛出,那么你不是还得执行一个 `t.join()`?显然逻辑不对,自然抛出。
211+
212+
至于这个**函数产生的异常,由调用方进行处理**,我们只是确保函数 f 中创建的线程正常执行完成,其局部对象正常析构释放。[测试代码](https://godbolt.org/z/jo5sPvPGE)
213+
214+
> 我知道你可能会想到:“我在 try 块中最后一行写一个 `t.join()` ,这样如果前面的代码没有抛出异常,就能正常的调用 join(),如果抛出了异常,那就调用 catch 中的 `t.join()` 根本不需要最外部 2 那里的 join(),也不需要再次 `throw` 抛出异常”
215+
>
216+
> ```cpp
217+
> void f(){
218+
> int n = 0;
219+
> std::thread t{ func{n},10 };
220+
> try{
221+
> // todo.. 一些当前线程可能抛出异常的代码
222+
> f2();
223+
> t.join(); // try 最后一行调用 join()
224+
> }
225+
> catch (...){
226+
> t.join(); // 如果抛出异常,就在 这里调用 join()
227+
> }
228+
> }
229+
> ```
230+
>
231+
> 你是否觉得这样也可以?也没问题?简单的[测试](https://godbolt.org/z/Wo7Tj95Tz)运行的确没问题。
232+
>
233+
> **但是这是不对的**,你要注意我们的注释:“**一些当前线程可能抛出异常的代码**”,而不是 `f2()`,我们的 `try` `catch` 只是为了让线程对象关联的线程得以正确执行完毕,以及线程对象正确析构。并没有处理什么其他的东西,不掩盖错误, `try` 块中的代码抛出了异常, `catch` 接住了,我们理所应当再次抛出。
211234
212235
### RAII
213236

0 commit comments

Comments
 (0)