Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/xamarin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 关闭Go中的自进给通道_Multithreading_Go_Concurrency_Channel_Goroutine - Fatal编程技术网

Multithreading 关闭Go中的自进给通道

Multithreading 关闭Go中的自进给通道,multithreading,go,concurrency,channel,goroutine,Multithreading,Go,Concurrency,Channel,Goroutine,我正在尝试使用Go中的并发和通道。我面临的问题主要是并发性的概念,因此我不会放弃以下逻辑是错误的或应该改变的观点 我有一个缓冲通道,缓冲区大小为'N',它还表示将创建的goroutine的数量。所有例程从一个通道读取,在另一个通道写入,主goroutine将打印来自最终通道的值 1个输入通道--N个GOROUTIES查找并添加到输入和输出--1个输出通道 问题是我总是遇到死锁,因为我不知道如何关闭一个正在自我馈送的通道,也不知道它何时停止,所以我也无法关闭输出通道 代码如下例所示: packag

我正在尝试使用Go中的并发和通道。我面临的问题主要是并发性的概念,因此我不会放弃以下逻辑是错误的或应该改变的观点

我有一个缓冲通道,缓冲区大小为'N',它还表示将创建的goroutine的数量。所有例程从一个通道读取,在另一个通道写入,主goroutine将打印来自最终通道的值

1个输入通道--N个GOROUTIES查找并添加到输入和输出--1个输出通道

问题是我总是遇到死锁,因为我不知道如何关闭一个正在自我馈送的通道,也不知道它何时停止,所以我也无法关闭输出通道

代码如下例所示:

package main

const count = 3
const finalNumber = 100

// There will be N routines running and reading from the one read channel
// The finalNumber is not known, in this examples is 100, but in the main problem will keep self feeding until the operation gives a wrong output
// readingRoutine will feed read channel and the print channel
func readingRoutine(read, print chan int) {
    for i := range read {
        print <- i
        if i < finalNumber && i+count < finalNumber {
            read <- i + count
        }
    }
}

// This is the main routine that will be printing the values from the print channel
func printingRoutine(print chan int) {
    for i := range print {
        println(i)
    }
}

func main() {
    read := make(chan int, count)
    print := make(chan int, count)

    // Feed count numbers into the buffered channel
    for i := 0; i < count; i++ {
        read <- i
    }

    // count go routines will be processing the read channel
    for i := 0; i < count; i++ {
        go readingRoutine(read, print)
    }
    printingRoutine(print)
}
主程序包
常数计数=3
常量最终编号=100
//将有N个例程运行并从一个读取通道读取
//最后的数字未知,在本例中为100,但在主要问题中,将保持自进给,直到操作给出错误的输出
//读取例行程序将为读取通道和打印通道馈电
func读取例程(读取、打印){
对于i:=范围读取{

打印您可以使用
sync.WaitGroup
等待事情完成,比如
wg:=&sync.WaitGroup{}

当您试图打印
finalNumber
次时,应调用
wg.Add(finalNumber)
,然后在
print()
中,每次打印完成后,调用
wg.done()

生成另一个goroutine以等待
wg.wait()
,然后关闭
read
频道和
print
频道

func printingRoutine(print chan int,wg *sync.WaitGroup) {
    for i := range print {
        println(i)
        wg.Done()
    }
}

func main() {
    read := make(chan int, count)
    print := make(chan int, count)
    wg := &sync.WaitGroup{}
    wg.Add(finalNumber)

    // Feed count numbers into the buffered channel
    for i := 0; i < count; i++ {
        read <- i
    }

    // count go routines will be processing the read channel
    for i := 0; i < count; i++ {
        go readingRoutine(read, print)
    }
    go func() {
        wg.Wait()
        close(read)
        close(print)
    }()
    printingRoutine(print,wg)
}
func打印例程(打印chan int,wg*sync.WaitGroup){
对于i:=范围打印{
println(i)
wg.Done()
}
}
func main(){
读取:=制造(成龙整数,计数)
打印:=制作(成行整数,计数)
wg:=&sync.WaitGroup{}
工作组添加(最终编号)
//将计数数字馈送到缓冲通道
对于i:=0;i阅读我通常会发现,如果你在设计模式或想法工作时遇到真正的问题,那你就是做错了。在这种情况下,自我喂食程序的想法应该知道它应该何时关闭

我想你想要的是一个
员工池的想法

基本上,您有一个通道,其中包含一组
工作
,然后是一些以go例程形式出现的
工作者
,他们从该通道读取作业,并对其进行处理,直到所有工作完成

在下面的示例中,我使用包来运行3个并发的worker,这些worker由第4个go例程提供

我等待所有工作人员关闭自己,这是由于输入工作通道关闭造成的

// create the channel to store the jobs
// notice that we can only have 5 jobs in the channel at one time
workChan := make(chan int, 5)

// here we define what should be happening in each of our workers.
// each worker will be running concurrently
var work gopool.WorkFunc = func(ctx context.Context) error {
    for {
        select {
        case <-ctx.Done():
            // this is just a get out clause in case we want to prematurely stop the workers while there is still work to do
            return ctx.Err()
        case work, ok := <-workChan:
            if !ok {
                // we get here if the work channel has been closed
                return nil
            }
            // do something with work here
            fmt.Println(work)
        }
    }
}

// this func defines how many workers we want to be running concurrently
var workerCount gopool.WorkerCountFunc = func() uint64 {
    return 3
}

// here we define a new worker pool
p := gopool.NewPool("test", work, workerCount, nil, context.TODO())

// here we start the worker pool
cancel, err := p.StartOnce()
if err != nil {
        panic(err)
}

// the workers are now running and waiting for jobs

// we'll defer the cancel to make sure that the pool will be closed eventually
defer cancel()

// now we'll start a go routine to feed the workers
// it does this by adding to the workChan, and closes workChan when there is no more work to do
// when the workChan is closed the workers know that they should quit
go func(workChan chan<- int, min int, max int) {
    for i := min; i <= max; i++ {
        workChan <- i
    }
    close(workChan)
}(workChan, 3, 200)

// now we wait for the pool to be finished with it's work
<-p.Done()

fmt.Println("all work has been done")
$ go run main.go 
4
6
7
8
9
10
3
5
13
14
15
16
17
18
12
20
21
19
23
24
25
22
27
28
11
30
31
26
33
29
35
36
34
38
39
32
41
42
37
44
43
46
47
40
49
50
51
52
48
54
53
56
57
58
45
60
61
62
63
64
65
55
59
68
69
66
71
72
73
70
75
76
77
67
79
80
74
82
83
81
85
84
87
88
89
78
91
90
93
94
92
96
97
95
99
98
101
102
103
104
100
106
107
108
109
105
111
112
110
114
115
116
117
118
119
120
86
122
123
124
125
126
127
121
129
113
131
128
133
134
130
136
137
132
139
138
141
140
143
144
145
146
147
148
149
150
135
151
153
142
155
156
157
158
159
160
161
162
163
164
152
154
167
165
166
170
171
172
173
174
169
176
177
178
179
180
168
182
183
184
181
185
187
188
189
190
175
186
193
191
195
194
197
196
199
198
200
192
all work has been done