Go 有没有什么优雅的方式可以暂停并继续其他的社交活动?
在我的例子中,我有数千个goroutine作为Go 有没有什么优雅的方式可以暂停并继续其他的社交活动?,go,channel,goroutine,Go,Channel,Goroutine,在我的例子中,我有数千个goroutine作为work()同时工作。我还有一个sync()goroutine。当sync启动时,我需要任何其他goroutine在同步作业完成后暂停一段时间。这是我的密码: var channels []chan int var channels_mutex sync.Mutex func work() { channel := make(chan int, 1) channels_mutex.Lock() channels = append(c
work()
同时工作。我还有一个sync()
goroutine。当sync
启动时,我需要任何其他goroutine在同步作业完成后暂停一段时间。这是我的密码:
var channels []chan int
var channels_mutex sync.Mutex
func work() {
channel := make(chan int, 1)
channels_mutex.Lock()
channels = append(channels, channel)
channels_mutex.Unlock()
for {
for {
sync_stat := <- channel // blocked here
if sync_stat == 0 { // if sync complete
break
}
}
// Do some jobs
if (some condition) {
return
}
}
}
func sync() {
channels_mutex.Lock()
// do some sync
for int i := 0; i != len(channels); i++ {
channels[i] <- 0
}
channels_mutex.Unlock()
}
var通道[]通道int
变量通道\u互斥同步。互斥
func工作(){
通道:=制造(通道内部,1)
通道\u互斥锁
通道=附加(通道,通道)
通道\u互斥锁。解锁()
为了{
为了{
sync_stat:=如果我理解正确,您需要N个工作进程和一个控制器,可以随意暂停、恢复和停止工作进程。下面的代码将实现这一点
package main
import (
"fmt"
"runtime"
"sync"
)
// Possible worker states.
const (
Stopped = 0
Paused = 1
Running = 2
)
// Maximum number of workers.
const WorkerCount = 1000
func main() {
// Launch workers.
var wg sync.WaitGroup
wg.Add(WorkerCount + 1)
workers := make([]chan int, WorkerCount)
for i := range workers {
workers[i] = make(chan int, 1)
go func(i int) {
worker(i, workers[i])
wg.Done()
}(i)
}
// Launch controller routine.
go func() {
controller(workers)
wg.Done()
}()
// Wait for all goroutines to finish.
wg.Wait()
}
func worker(id int, ws <-chan int) {
state := Paused // Begin in the paused state.
for {
select {
case state = <-ws:
switch state {
case Stopped:
fmt.Printf("Worker %d: Stopped\n", id)
return
case Running:
fmt.Printf("Worker %d: Running\n", id)
case Paused:
fmt.Printf("Worker %d: Paused\n", id)
}
default:
// We use runtime.Gosched() to prevent a deadlock in this case.
// It will not be needed of work is performed here which yields
// to the scheduler.
runtime.Gosched()
if state == Paused {
break
}
// Do actual work here.
}
}
}
// controller handles the current state of all workers. They can be
// instructed to be either running, paused or stopped entirely.
func controller(workers []chan int) {
// Start workers
setState(workers, Running)
// Pause workers.
setState(workers, Paused)
// Unpause workers.
setState(workers, Running)
// Shutdown workers.
setState(workers, Stopped)
}
// setState changes the state of all given workers.
func setState(workers []chan int, state int) {
for _, w := range workers {
w <- state
}
}
主程序包
进口(
“fmt”
“运行时”
“同步”
)
//可能的工人国家。
常数(
停止=0
暂停=1
运行=2
)
//工人的最大数量。
常数工作计数=1000
func main(){
//发射工人。
var wg sync.WaitGroup
工作组添加(工作计数+1)
工人:=制造([]成交量,工人计数)
对于i:=范围工人{
工人[i]=制造(chan int,1)
go func(i int){
工人(i,工人[i])
wg.Done()
}(一)
}
//启动控制器例行程序。
go func(){
管制员(工人)
wg.Done()
}()
//等待所有goroutine完成。
wg.Wait()
}
func工人(id int,ws What do`使用通道进行通信是Go中实现这一点的惯用方法。如果您愿意,可以使用全局变量。但是我建议不要使用sync.Mutex
来锁定它。在处理大量goroutine时,它们的伸缩性不太好,每个goroutine都会获取R/W锁。在这种情况下,我将使用e> sync/atomic
package以原子方式读取/写入状态。@jimt很好的示例;很好地提醒了当通道被阻塞时“默认”是如何运行的。我要补充的是,如果工作人员有时需要一段时间才能返回读取状态,那么最好让与他们对话的通道具有1的缓冲区,这样您就可以在同一时间内写入所有通道快点,不要暂停或停止2号,直到1号停止,等等。或者我误解了它的工作原理吗?也许我遗漏了一些东西,但暂停的工作人员不会继续运行(由于选择的默认部分)。我认为这将导致大量的unnec.线程上下文切换。是的,它将继续进入默认情况,但它并不像您预期的那样昂贵。它的作用是将状态设置为适当的值。这取决于您决定是否以及如何限制循环。就上下文切换而言,非常彻底的e解释这在围棋中是如何工作的。