英文:
GoLang, put resource back to channel hang my program
问题
这段代码中的问题可能是由于通道的阻塞导致的hang。在这段代码中,当ret
为真时,会执行mr.registerChannel <- worker_str
这一行代码,将worker_str
放回registerChannel
通道中。但是,如果没有其他goroutine从registerChannel
中接收数据,那么这个操作将会导致阻塞,从而导致hang。
为了解决这个问题,你可以考虑使用带有缓冲区的通道,或者在接收数据之前使用非阻塞的方式发送数据。如果你使用带有缓冲区的通道,可以在初始化registerChannel
时指定缓冲区的大小,例如registerChannel := make(chan string, bufferSize)
。这样,即使没有其他goroutine从通道中接收数据,发送操作也不会阻塞,直到缓冲区被填满。
另外,你还可以使用select
语句来实现非阻塞的发送操作。你可以将发送操作放在一个select
语句中,并使用default
分支来处理通道已满的情况。例如:
select {
case mr.registerChannel <- worker_str:
// 发送成功
default:
// 通道已满,执行其他操作
}
通过这样的方式,即使通道已满,发送操作也不会阻塞,而是会执行default
分支中的代码。
希望这些解释对你有帮助!如果还有其他问题,请随时提问。
英文:
for i := 0; i < mr.nMap; i++ {
DPrintf("worker number is %d\n", mr.workerNumber)
worker_str = <- mr.registerChannel
DPrintf("Worker_str is %s \n",worker_str)
args := &DoJobArgs{mr.file,"Map",i,mr.nReduce}
var reply DoJobReply
var ret bool
ret = call(worker_str, "Worker.DoJob", args, &reply)
if ret {
fmt.Println("wk worker done.\n")
fmt.Println(worker_str)
mr.registerChannel <- worker_str // <=======stuck here
} else
{
fmt.Println("wk worker fail.\n")
}
DPrintf("map finished.")
}
btw, mr is instance of this:
type MapReduce struct {
nMap int // Number of Map jobs
nReduce int // Number of Reduce jobs
file string // Name of input file
MasterAddress string
registerChannel chan string
DoneChannel chan bool
alive bool
l net.Listener
stats *list.List
// Map of registered workers that you need to keep up to date
Workers map[string]*WorkerInfo
// add any additional state here
workerNumber int
}
My code hang when I do this "mr.registerChannel <- worker_str "
I really don't understand why.
worker_str is available, and I want to put this resource back after using this worker. Put it back to channel, let next job use available workers.
Why it hang?
thanks
答案1
得分: 6
在Go语言中,如果通道没有缓冲区,它们可以用于同步。在这里,负责消费mr.registerChannel
的进程试图向其写入数据。当你从非缓冲通道读取或写入数据时,你会等待直到另一端有进程进行读取或写入。
因此,当这个代码块试图向通道写入数据时,它会阻塞等待其他进程读取它所写入的数据。由于这个代码块还负责读取数据,它将永远等待自己,导致死锁。你需要重新设计代码,将字符串传递给其他进程进行读取,或者使用带缓冲区的通道,并且不期望在读取行worker_str = <- mr.registerChannel
上发生阻塞。这将需要重写为for/select或其他形式的代码。
英文:
In go, channels can be used for synchronization if they are not buffered. Here, the process that is responsible for consuming the mr.registerChannel
is trying to write to it. When you read from, or write to and unbuffered channel, you will wait until there is another process on the other end to write to, or read from the channel, respectively.
So, when this block attempts to write to the channel, it blocks waiting for someone to read what it wrote. Since this block is also responsible for reading, it will wait forever for itself in a deadlock. You need to either redesign this so that you hand the string back off to something else to read, or you need to use a buffered channel and don't expect to trap on the read line worker_str = <- mr.registerChannel
. That would have to be re-written as a for/select or something.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论