英文:
Channel never dies although closed
问题
在下面的代码中,我试图将发送到inputs通道的所有文件写入,并通过operationOutcomes通道发送相应的响应。
main.go
package main
import(
lr "github.com/fabulousduck/librarian"
"fmt"
)
func main() {
writeOpCount := 100;
operationOutcomes, inputs := make(chan lr.WriteOpResponse), make(chan lr.WriteOp)
go lr.WriteC(inputs, operationOutcomes)
for i := 0; i < writeOpCount; i++ {
inputs <- lr.WriteOp{ Dest: `../exampleFiles/createdFiles/{i}.txt`, Content: `Invoice #{i}` }
}
close(inputs)
for i := 0; i < writeOpCount; i++ {
writeResult := <-operationOutcomes
fmt.Println("Response from write operation : ", writeResult.Msg, "err ", writeResult.Err, "bytes written : ", writeResult.BytesWritten)
}
close(operationOutcomes)
}
librarian.go
package librarian
import(
"os"
"fmt"
)
type WriteOp struct {
Dest, Content string
}
type WriteOpResponse struct {
Msg error
Err bool
BytesWritten int
}
func WriteC (inputChannel <-chan WriteOp, outputChannel chan<- WriteOpResponse) {
workOp := <-inputChannel
go writeWorker(workOp, outputChannel)
}
func writeWorker (job WriteOp, outGoing chan<- WriteOpResponse) {
file, err := os.OpenFile(job.Dest, os.O_RDWR, 0666)
if err != nil {
fmt.Println("err : ", err)
outGoing <- WriteOpResponse{ Msg: err, Err: true, BytesWritten: 0 }
}
bytesWritten , err := file.WriteString(job.Content)
if err != nil {
outGoing <- WriteOpResponse{ Msg: err, Err: true, BytesWritten: 0 }
}
outGoing <- WriteOpResponse{ Msg: nil, Err: false, BytesWritten: bytesWritten }
}
无论是否出现错误,这两种情况都会导致死锁,即使我在使用完它们后关闭了两个通道。
英文:
In the following code, i am trying to write all files that are sent to the inputs channel and send a corresponding response over the operationOutcomes channel
main.go
package main
import(
lr "github.com/fabulousduck/librarian"
"fmt"
)
func main() {
writeOpCount := 100;
operationOutcomes, inputs := make(chan lr.WriteOpResponse), make(chan lr.WriteOp)
go lr.WriteC(inputs, operationOutcomes)
for i := 0; i < writeOpCount; i++ {
inputs <- lr.WriteOp{ Dest: `../exampleFiles/createdFiles/{i}.txt`, Content: `Invoice #{i}` }
}
close(inputs)
for i := 0; i < writeOpCount; i++ {
writeResult := <-operationOutcomes
fmt.Println("Response from write operation : ", writeResult.Msg, "err ", writeResult.Err, "bytes written : ", writeResult.BytesWritten)
}
close(operationOutcomes)
}
librarian.go
package librarian
import(
"os"
"fmt"
)
type WriteOp struct {
Dest, Content string
}
type WriteOpResponse struct {
Msg error
Err bool
BytesWritten int
}
func WriteC (inputChannel <-chan WriteOp, outputChannel chan<- WriteOpResponse) {
workOp := <-inputChannel
go writeWorker(workOp, outputChannel)
}
func writeWorker (job WriteOp, outGoing chan<- WriteOpResponse) {
file, err := os.OpenFile(job.Dest, os.O_RDWR, 0666)
if err != nil {
fmt.Println("err : ", err)
outGoing <- WriteOpResponse{ Msg: err, Err: true, BytesWritten: 0 }
}
bytesWritten , err := file.WriteString(job.Content)
if err != nil {
outGoing <- WriteOpResponse{ Msg: err, Err: true, BytesWritten: 0 }
}
outGoing <- WriteOpResponse{ Msg: nil, Err: false, BytesWritten: bytesWritten }
}
This throws a deadlock in both cases when there is and isn't an error, even though i am closing both channels when i am done with them ?
答案1
得分: 1
你只读取了operationOutcomes到writeOpCount次数,即使在writeWorker中,每次执行都可能导致在该通道上写入多达3条消息(没有错误情况会导致函数返回,因此它会继续处理)。由于它是无缓冲的并且停止被读取,所以在某个时刻,写入该通道的工作线程将无法再添加消息,从而永久锁定。
此外,由于你只调用了一次WriteC且没有循环,它只会从inputs中读取和处理一条消息。如果writeOpCount大于1,则在第一次循环中尝试排队第二条消息时,它将永久锁定。
英文:
You only read from operationOutcomes up to writeOpCount times, even though in writeWorker each execution can result in up to 3 messages being written on that channel (none of your error cases causes the function to return, to it continues processing). Because it's unbuffered and it stops being read, at some point the workers writing to it can no longer add messages and so lock forever.
Also, since you only call WriteC once and it does not loop, it will only ever read and process one message from the inputs. If writeOpCount is > 1, then it will lock forever within the first loop when it tries to queue a second message.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论