-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
c3ac38c
commit fc13e78
Showing
2 changed files
with
33 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package myonce | ||
|
||
import ( | ||
"sync" | ||
"sync/atomic" | ||
) | ||
|
||
type MyOnce struct { | ||
done uint32 | ||
} | ||
|
||
func (o *MyOnce) Do(mu *sync.Mutex, f func()) { | ||
|
||
if atomic.LoadUint32(&o.done) == 0 { | ||
|
||
o.doSlow(mu, f) | ||
} | ||
} | ||
|
||
// 这里与标准库的做法不一样,标准库是保证了f执行之后才会设置done为1 | ||
// 这里是先设置done为1,然后再执行f | ||
// 标准库是站在资源必须初始化成功的角度设计,而这里主要是为了解决资源释放自己调用自己的死锁问题 | ||
// 试想下这个场景; | ||
// 出错会调用用户的OnClose函数,这个函数会被包在sync.Once里面,而OnClose函数中又会调用Close函数,这个函数里面也会有调用OnClose的逻辑,这样就会死锁 | ||
// 如果前置设置done为1,那么就不会有这个问题 | ||
func (o *MyOnce) doSlow(mu *sync.Mutex, f func()) { | ||
mu.Lock() | ||
defer mu.Unlock() | ||
if o.done == 0 { | ||
atomic.StoreUint32(&o.done, 1) | ||
f() | ||
} | ||
} |