From 0da950002771a4122714acdd7bb8b422022754cd Mon Sep 17 00:00:00 2001 From: iepngs Date: Thu, 11 Jul 2019 12:11:34 +0800 Subject: [PATCH] =?UTF-8?q?pool.Mu.Lock()=E4=B8=ADlock=E6=96=B9=E6=B3=95?= =?UTF-8?q?=E9=A6=96=E5=AD=97=E6=AF=8D=E9=9C=80=E8=A6=81=E5=A4=A7=E5=86=99?= =?UTF-8?q?=EF=BC=9B=E5=88=87=E7=89=87=E5=90=8D=E7=A7=B0=E9=94=99=E8=AF=AF?= =?UTF-8?q?=EF=BC=9Bprocess=E7=9A=84=E5=8F=82=E6=95=B0=E7=B1=BB=E5=9E=8B?= =?UTF-8?q?=E5=BA=94=E8=AF=A5=E4=B8=8A=E4=B8=8B=E6=96=87=E7=BB=9F=E4=B8=80?= =?UTF-8?q?=EF=BC=9B=20(#656)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- eBook/14.7.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/eBook/14.7.md b/eBook/14.7.md index 299fa50..ee94901 100644 --- a/eBook/14.7.md +++ b/eBook/14.7.md @@ -15,7 +15,7 @@ type Task struct { ```go type Pool struct { Mu sync.Mutex - Tasks []Task + Tasks []*Task } ``` sync.Mutex([参见9.3](09.3.md)是互斥锁:它用来在代码中保护临界区资源:同一时间只有一个go协程(goroutine)可以进入该临界区。如果出现了同一时间多个go协程都进入了该临界区,则会产生竞争:Pool结构就不能保证被正确更新。在传统的模式中(经典的面向对象的语言中应用得比较多,比如C++,JAVA,C#),worker代码可能这样写: @@ -23,10 +23,10 @@ sync.Mutex([参见9.3](09.3.md)是互斥锁:它用来在代码中保护临界 ```go func Worker(pool *Pool) { for { - pool.Mu.lock() + pool.Mu.Lock() // begin critical section: - task := pool.Task[0] // take the first task - pool.Tasks = pool.Task[1:] // update the pool of tasks + task := pool.Tasks[0] // take the first task + pool.Tasks = pool.Tasks[1:] // update the pool of tasks // end critical section pool.Mu.Unlock() process(task) @@ -34,7 +34,7 @@ func Worker(pool *Pool) { } ``` -这些worker有许多都可以并发执行;他们可以在go协程中启动。一个worker先将pool锁定,从pool获取第一项任务,再解锁和处理任务。加锁保证了同一时间只有一个go协程可以进入到pool中:一项任务有且只能被赋予一个worker。如果不加锁,则工作协程可能会在`task:=pool.Task[0]`发生切换,导致`pool.Tasks=pool.Task[1:]`结果异常:一些worker获取不到任务,而一些任务可能被多个worker得到。加锁实现同步的方式在工作协程比较少时可以工作的很好,但是当工作协程数量很大,任务量也很多时,处理效率将会因为频繁的加锁/解锁开销而降低。当工作协程数增加到一个阈值时,程序效率会急剧下降,这就成为了瓶颈。 +这些worker有许多都可以并发执行;他们可以在go协程中启动。一个worker先将pool锁定,从pool获取第一项任务,再解锁和处理任务。加锁保证了同一时间只有一个go协程可以进入到pool中:一项任务有且只能被赋予一个worker。如果不加锁,则工作协程可能会在`task:=pool.Tasks[0]`发生切换,导致`pool.Tasks=pool.Tasks[1:]`结果异常:一些worker获取不到任务,而一些任务可能被多个worker得到。加锁实现同步的方式在工作协程比较少时可以工作的很好,但是当工作协程数量很大,任务量也很多时,处理效率将会因为频繁的加锁/解锁开销而降低。当工作协程数增加到一个阈值时,程序效率会急剧下降,这就成为了瓶颈。 新模式:使用通道 @@ -104,4 +104,4 @@ worker的逻辑比较简单:从pending通道拿任务,处理后将其放到d - [目录](directory.md) - 上一节:[协程和恢复(recover)](14.6.md) -- 下一节:[惰性生成器实现](14.8.md) \ No newline at end of file +- 下一节:[惰性生成器实现](14.8.md)