感觉 sync.Pool 很容易用错

Pool.Put 应该只放入不再使用的对象,但在并发环境中,往往很难准确确定一个对象不被使用的时机,所以可能出现仍在使用的对象被放入了池中。如果这个对象再被Get出来,就有可能两个 gorouten 访问同一个对象了。举个例子:


一个打印任务的Pool,打印完成后 任务 会被放入 Pool 中以便再次利用。但客户端也会查询任务状态,就可能出现:



  1. 查询状态时拿到了任务对象

  2. 打印任务完成,对象被放入池中

  3. 一个新任务到来,对象被取出再利用

  4. 第1步读取任务对象的信息,此时可能读到第3步被修改了的对象


还有是 Pool.Get 出来的对象,并不是 zero initialized,不小心的话也可能会出问题,比如改代码增加了一个字段,但Get后忘了把它置成合理值。

已邀请:

simple - 分布式 & Java & Go

赞同来自:

这个怎么说呢,首先要真想用好一个工具,还是需要去了解它的工作原理和使用场景。如果从sync.Pool拿出来的临时对象会在不同的goroutine之间传递,那就不要在放回了算了。

傅小黑

赞同来自:

取出来了要保证用完了再放回去啊。
没用完就放回去,再被别人用,是本身逻辑的问题
如果保证不了还是不要随便用 pool

lrita

赞同来自:

不要把代码设计问题归罪与一个库的实现/或者用法上。

philc - https://github.com/philchia

赞同来自:

取出来后或者放进去前要做一次重置的哦

tpkeeper - Software Engineer. Gopher. [ tpkeeper.me@gmail.com ]

赞同来自:

可以参考gin框架中pool的使用,取出之后reset

要回复问题请先登录注册