go面试题:不使用 sync.Once()并且不加互斥锁,如何实现多线程场景中一个方法只被执行一次
实现思路:多个携程去执行一个方法,每个携程开始时从channel中取数据,因为此时channel中没有数据,所以执行方法的携程阻塞等;
单独开启一个携程往channel中写入数据,此时第一个读取到管道数据的携程去执行方法,执行完毕关闭通道,后续所有携程检测到通道关闭则直接return
代码如下:
package main
import (
"fmt"
"time"
)
type Once struct {
ch chan bool
}
func NewChan() *Once {
return &Once{ch: make(chan bool, 1)}
}
// 方法一开始读管道数据,因为没有数据,阻塞
func (o *Once) Do(f func()) {
k, v := <-o.ch
// 通道关闭则直接退出程序
if !v {
fmt.Println("exit")
return
} else { //读取到数据,执行方法,同时关闭通道
f()
fmt.Println(k)
close(o.ch)
}
}
func main() {
once := NewChan()
// 开携程,往管道中写入数据
go func() {
time.Sleep(3 * time.Second)/*睡眠三秒,模拟代码执行时间*/
fmt.Println("go func exec ...")
once.ch <- true
}()
// 多线程执行一个方法,确保该方法只被执行一次
for i := 0; i < 100; i++ {
go once.Do(test)
}
time.Sleep(30 * time.Second)
}
func test() {
fmt.Println("code...")
return
}