利用atomic递增
对书中的事例进行了修改,利用atomic对count进行递增,同步计数。
var (
shutdown int32
count int64
wg sync.WaitGroup
)
func doWork(name string) {
defer wg.Done()
for {
fmt.Printf("Doing %s Work\n", name)
time.Sleep(250 * time.Millisecond)
if atomic.LoadInt32(&shutdown) == 1 {
fmt.Printf("shuting %s down\n", name)
break
}
}
}
func doIncre(name string) {
defer wg.Done()
for {
fmt.Printf("Doing %s Work\n", name)
atomic.AddInt64(&count, 1)
time.Sleep(250 * time.Millisecond)
if atomic.LoadInt32(&shutdown) == 1 {
fmt.Printf("shuting %s down\n", name)
break
}
}
}
func main() {
wg.Add(2)
go doIncre("A")
go doIncre("B")
time.Sleep(1 * time.Second)
fmt.Println("shut down now")
atomic.StoreInt32(&shutdown, 1)
fmt.Printf("count is %v\n", atomic.LoadInt64(&count))
wg.Wait()
}
关键在于
atomic.StoreInt32(&shutdown, 1)
if atomic.LoadInt32(&shutdown) == 1 {
和
atomic.LoadInt64(&count)
atomic.AddInt64(&count, 1)
Channels
Unbuffered channels
利用无缓存通道实现流水工作。
关键在于第一个工作执行时启动第二个工作,第一个工作执行和第二个工作共享一个Unbuffered channel,第二个工作执行前等待channel的数据到来,第一个工作执行完后往channel写入数据,写入时流水就从第一个工作走到第二工作。
func main() {
baton := make(chan int)
wg.Add(1)
go Runner(baton)
baton <- 1
wg.Wait()
}
func Runner(baton chan int) {
var newRunner int
runner := <-baton
fmt.Printf("Runner %d Running With Baton\n", runner)
if runner != 6 {
newRunner = runner + 1
fmt.Printf("Runner %d To The Line\n", newRunner)
go Runner(baton)
} else {
fmt.Printf("Runner %d Finished, Race Over\n", runner)
wg.Done()
return
}
time.Sleep(100 * time.Millisecond)
fmt.Printf("Runner %d Exchange With Runner %d\n", runner, newRunner)
baton <- newRunner
}
关键代码
Runner函数刚进入时,等待baton
runner :=baton
获取baton后,不是最后一个的话,启动另外一个Runner,这个Runner等待baton。
newRunner = runner + 1
fmt.Printf("Runner %d To The Line\n", newRunner)
go Runner(baton)
当前Runner完成后,
baton <- newRunner
当前Runner和下一个Runner据交换之前都是锁定的。
Buffered channels
当一个channel关闭,仍然可以在这个通道上执行读操作,不过不可以再往里面写入。关闭后仍然可以读,保证了channel的数据能够被全部读取而不会丢失。
后记
之前一直在CSDN上写文章,后面会逐步转换到简书上,还请大家多多支持。