由于go是并发程序语言,并使用channel
(我几乎使用它所有代码)或其他内容来同步goroutine
。
而且我也知道要使用调度程序来安排goroutine
,这意味着你应该在每个goroutine中调用scheduler
(通道操作,runtime.goSche或其他)并保证它会被执行。
以上是go
的所有限制,我用它来设计我的代码。
但我也发现在我的代码中会发生代码阻塞。并且很难找到阻塞的原因(甚至使用 GDB )。
我错过了什么吗?
还有什么可能导致阻止?
我应该注意什么?
[编辑] :好的,因为我项目的代码有点大。我决定不显示标准 go
代码,只是可能导致代码阻塞的部分的一般概念。以下是我项目中文件传输模块的一些代码:
func(c *client)listenRead() {
for {
_ := websocket.JSON.Receive(c.ws, &package)
switch package.Op {
case fileUpld:
c.fileMan.store <- package.Body
case fileDownld:
c.fileMan.downld <- package.Body
case c.xxx:
...
default:
// bad package.
}
}
}
客户端通过来自其他客户端的websocket收听和接收消息,然后根据package
的{{1}}字段将包转发给不同的处理程序,例如Op
如下所示。
fileManager
当{strong> chan func(fm *fileManager) fileRouter() {
for {
select {
case fs := <-fm.fileUpld:
if window < filesize {
f.Write(fs.content) // client A write to file
window += fs.contSize
} else {
f.close() // close file
}
case fd := fm.downld:
go fm.downldFile(fd)
}
}
}
获取从fileManger
发送的数据时,fileUpld
可以接收文件并存储到服务器。它可以在从客户端收到client
时下载文件,并生成request
来完成工作,如下所示:
goroutine
我的文件传输模块的主要想法是客户端A 想要将文件发送到客户端B ,并且不希望等待来自客户端B 的func(fm *fileManager) downldFile(fd) {
f := getFile(fd) // get the file that client A write
b := make([]byte, SeqLength)
for {
if convergence < window {
f.Read(b)
// wrap 'b' to package 'p', for send
fm.server.send <- p // send to client B
} else if window < fileSize {
runtime.Goshed()
} else {
// download done.
fm.done <- xx
return
}
}
}
,这意味着它将首先存储到服务器,然后客户端B 将通过从服务器下载来获取该文件。但客户端B 可能会在客户端A 上传文件时下载文件。因此上传和下载之间需要同步。
我使用三个变量来实现此目的:窗口,收敛, filesize 。当客户端A 上传(写入)文件时,窗口会增加它写入的字节的值。当客户端B 下载(读取)文件时,收敛将增加它读取的字节数。 acceptance
只发生Write
而window < filesize
仅发生read
。就像:
convergence < window
我知道这会导致数据争用,但它也保证+-----------+---------------+--------------+
|############|||||||||||||||| |
+-----------+---------------+--------------+
^ ^ ^
| | |
convergence window filesize
不会读取read
尚未写入的内容。( BTW :我没有使用write
来实现它的解决方案。)
当我尝试同时上传和下载时,会发生代码阻塞(我放慢客户端A 来实现它)。但是当我将channel
设置为2时,它没有问题。
答案 0 :(得分:0)
你应该考虑一个垃圾收集器来暂停整个程序,所谓的“停止世界”。在具有大内存消耗的大型应用程序中,GC可以“停止世界”长达10秒,但这是最糟糕的情况。以下是Go中关于GC的一个很好的答案:What kind of Garbage Collection does Go use?