I want to create a producer/consumer with manager program in Go. For example: I have a 5 producers, 5 consumers and manager. Producers have their own local arrays, they iterate over them and send the elements to the manager. Consumers have their own local arrays with info that elements consume; they send them to the manager too. The Manager has it own array, where it stores what and how many elements there are (for example - if the producer sends 1 1 2 3 1 2 0 elements, the manager array looks like 1 3 2 1 (one 0, three 1, two 2 and one 3 ) and it handles producers' and consumers' requests - placing an element into the array (produce) or removing it (consume).
Is it possible to make a program like this in Go? I already did this in JAVA + CSP with channels to send info and guards in the manager to determine which procedure should be done first when producer and consumer try to process the same element (for example, a producer wants to add 1 to the manager array and at the same time a consumer wants to consume 1).
Any examples or advice are welcome, because I don't find any info about what I want to do. If needed I can give my JAVA+CSP code.
UPDATE. How about synchronization (not to take from empty array)? For example - if consumer wants to consume element from manager array that does not exist yet (for example consumer wants to consume '3', but manager don't have any of thems) but producer has this element and it will be produced after few iterations - how can I make consumers to check manager array again and again until producers work is finished? Should I need to create structs (or classes) for consumers elements and mark that they are used or not, or Go has specific methods to do this?
Here's a full example, including channel cleanup. After all the consumers and producers are finished, the Manager prints out the result (for which I've used a map rather than a slice, since I think it makes the code a tad easier).
package main
import "fmt"
// Consume processes the numbers in ns, sending them on ch after they're
// processed. When the routine is finished, it signals that on done.
func Consume(done chan bool, ch chan int, ns []int) {
for i := range ns {
ch <- i
}
done <- true
}
// Produce "creates" the numbers in ns, sending them on ch after they're
// produced. When the routine is finished, it signals that on done.
func Produce(done chan bool, ch chan int, ns []int) {
for i := range ns {
ch <- i
}
done <- true
}
// Manage creates consumers and producers for the given int slices.
// It returns once all consumers and producers are finished.
func Manage(cons, pros [][]int) {
cch := make(chan int)
pch := make(chan int)
dch := make(chan bool)
n := len(cons) + len(pros)
data := make(map[int]int)
for _, c := range cons {
go Consume(dch, cch, c)
}
for _, p := range pros {
go Produce(dch, pch, p)
}
for n > 0 {
select {
case c := <-cch:
data[c] -= 1
case c := <-pch:
data[c] += 1
case <-dch:
n -= 1
}
}
close(cch)
close(pch)
close(dch)
fmt.Println(data)
}
func main() {
cons := [][]int{{1, 3, 5}, {0, 1, 5}}
pros := [][]int{{0, 1, 1}, {3, 5, 5, 7}}
Manage(cons, pros)
}
I did a very similar example to what you're trying to do, check this gist github gist
The way I implemented that is using a single channel for my process consumer and another for my 2x processes that produce items, the for block controls the push from producers to the consumer and whenever the producers arent pushing anything the loop will default. The objects moved through the channels are slices, processes would produce and consume the headlines in each slice sent through the channel. I believe you can adjust this code to fit your example.
Related
i have an problem with GCD in swift 3
i create the concurrent queue and i pass function in this queue this function call another function
i need to print the elapsed time for each call
but i think the implementation is cut within the concurrent queue the following my code :
// peform task with the concurrent queue
class DoCalculations{
func doCalc() {
let x = 100
let y = x * x
_ = y / x
}
func performCalculation(itretion:Int,tag:String) {
let start = CFAbsoluteTimeGetCurrent()
for _ in 0..<itretion {
self.doCalc()
}
let end = CFAbsoluteTimeGetCurrent()
print("tag :\(tag) : \(end - start)")
}
}
let calc = DoCalculations()
let cQueue = DispatchQueue(label: "com.myCompany", attributes: .concurrent)
cQueue.async {
calc.performCalculation(itretion: 1000000, tag: "sync1")
}
cQueue.async {
calc.performCalculation(itretion: 1000, tag: "sync2")
}
cQueue.async {
calc.performCalculation(itretion: 100000, tag: "sync3")
}
// the print function is not Excuted
please can solve this issues
If you're doing this on a playground, you want to indicate that execution should continue "after the end of the playground’s top-level code is reached." You do this with needsIndefiniteExecution:
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
As the documentation for needsIndefiniteExecution says:
A Boolean value that indicates whether indefinite execution is enabled.
By default, all top-level code is executed, and then execution is terminated. When working with asynchronous code, enable indefinite execution to allow execution to continue after the end of the playground’s top-level code is reached. This, in turn, gives threads and callbacks time to execute.
Editing the playground automatically stops execution, even when indefinite execution is enabled.
Set needsIndefiniteExecution to true to continue execution after the end of top-level code. Set it to false to stop execution at that point.
The default value is false. It is set to true when liveView is set to a non-nil value.
Example of concurrent queue using gcd
func callGCDWithConcurrentQueue(){
let dispatchQueue = DispatchQueue(label: "Dmoe",qos:.utility,attributes: .concurrent)
dispatchQueue.async{ // Task 1
for i in 0...10{
print(i)
}
}
dispatchQueue.async{ //Task 2
for i in 10...20{
print(i)
}
}
}
callGCDWithConcurrentQueue() > // Calling Method
// OutPut
/
0
10
1
2
3
4
11
5
6
7
8
9
10
12
13
14
15
16
17
18
19
20
/
I was following the Go Tour and I am a bit stuck when it comes to goroutines. I understand that they are very lightweight and that every time a goroutine blocks, another one will start but I can't get my head around how this example actually works:
package main
import (
"fmt"
"time"
)
func say(s string) {
for i := 0; i < 5; i++ {
time.Sleep(1000 * time.Millisecond)
fmt.Println(s)
}
}
func main() {
go say("world")
say("hello")
}
Playground
I understand that a goroutine is started for the say function with the argument "world", but as far as I understand that should print "world" five times and "hello" once. However I don't understand why the output is as it is:
hello
world
hello
world
hello
world
hello
world
hello
From my limited understanding of threads from other languages the output should have been something like this:
hello
world
world
world
world
world
or like this:
world
world
world
hello
world
world
Why does the second line execute five times as well? Does anything below a go statement classify as part of the go routine?
Also the next slide shows something I can't get my head round again:
package main
import "fmt"
func sum(a []int, c chan int) {
sum := 0
for _, v := range a {
sum += v
}
c <- sum // send sum to c
}
func main() {
a := []int{7, 2, 8, -9, 4, 0}
c := make(chan int)
go sum(a[:len(a)/2], c)
go sum(a[len(a)/2:], c)
x, y := <-c, <-c // receive from c
fmt.Println(x, y, x+y)
}
Playground
A goroutine is started for the second half of the slice and then another one for the first part of the slice, however the values x and y have been assigned two different values. The way I see it the sum function will send it's sum to channel c and then the next sum will send it's sum to the same channel c so how can the two variables be assigned two different values? Shouldn't channel c have one single sum value in there?
I appreciate that this is quite a long question but I wasn't able to find the answer to these questions.
Why does the second line execute 5 times as well?
The second line will print hello every second 5 times in the main() thread.
But concurrently the first line go say("world") will also print world every seconds five times in a separate goroutine.
The Sleep ensure that each routine yields, allowing the other to resume.
Hence the output:
hello
world
hello
world
hello
world
hello
world
hello
The way I see it the sum function will send it's sum to channel c and then the next sum will send it's sum to the same channel c so how can the two variables be assigned two different values?
Because each send will block on c until channel c is read.
Since there are two write to c, you need to read:
x, y := <-c, <-c // receive from c twice.
The Assignement section of Golang Spec allows for a tuple assignment if:
the number of operands on the left must equal the number of expressions on the right, each of which must be single-valued, and the nth expression on the right is assigned to the nth operand on the left.
For the first function you should see values in the style VonC presented. The reason hello prints 5 times as well is because the function say prints things 5 times. Just imagine the program without the goroutine. I think it doesn't guarantee that you will get hello and world perfectly interspersed but I may be wrong.
The reason the channel works is:
Golang let's you do multiple assignment as VonC mentions
Channels empty out, i.e. when you assign c to x it removes the first sum that was passed into the channel and when it assigns c to y it passes in the second value (again I think the order is not a guarantee as x could have the first half and y the second half sum or vice-versa.
If you imagine channels as a sort of a queue I think it makes more sense. The summing goroutines push values onto the queue and assignments pop the values sequentially.
When executing the following code I get what I expect when the first loop is done (sequence from 0 to 9). But when the second loop finishes, the result is not what I expected (I expected the same result as in the first loop, but it prints only '10's):
package main
import (
"fmt"
"sync"
)
func main() {
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func(j int) {
defer wg.Done()
fmt.Println(j)
}(i)
}
wg.Wait()
fmt.Println("done first")
for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
defer wg.Done()
fmt.Println(i)
}()
}
wg.Wait()
fmt.Println("done second")
}
Output:
0
1
2
3
4
5
6
7
8
9
done first
10
10
10
10
10
10
10
10
10
10
done second
Why doesn't the second loop print a sequence?
Because the first one gets a copy of the loop counter each time. Whereas the second gets the variable captured as part of a closure.
In the first, you're passing it in here in every iteration of the loop:
go func(j int) {
defer wg.Done()
fmt.Println(j)
}(i) // <------------ its passed in here as part of each loop iteration
The second one receives nothing.. so, the loop counter i is captured as part of a closure. By the time the first go routine executes, the for loop has finished. The loop finishing has set the i variable (that is now part of a closure) to 10. Go routine #1 executes and prints the value of i.. which is now already 10 and the rest follow suit.
TLDR: The problem here is that the loop is finishing before any go routines are scheduled to be run - its just that quick. Therefore, i == 10 when the go routines run.
I am new to Golang. Right now I am trying to figure out how to make an any-to-one channel in Golang, where the setup is as follows:
say I have two goroutines numgen1 and numgen2 executing concurrently and writing numbers to channels num1 resp. num2. I would like to add the numbers sent from numgen1 and numgen2 in a new process, addnum. I have tried something like this:
func addnum(num1, num2, sum chan int) {
done := make(chan bool)
go func() {
n1 := <- num1
done <- true
}()
n2 := <- num2
<- done
sum <- n1 + n2
}
but this seems sadly incorrect. Could someone please give me some ideas?
Thank you very much for your help.
Depending on your requirements, you may need to read both of the channels for every iteration (i.e. a sort-of 'zip' function). You can do this with a select, similarly to user860302's answer:
func main() {
c1 := make(chan int)
c2 := make(chan int)
out := make(chan int)
go func(in1, in2 <-chan int, out chan<- int) {
for {
sum := 0
select {
case sum = <-in1:
sum += <-in2
case sum = <-in2:
sum += <-in1
}
out <- sum
}
}(c1, c2, out)
}
This runs forever. My preferred way to terminate goroutines like this one is to close the input channels. In this case you would need to wait for both to close, then close(out) before terminating.
Tip: note the use of directional channels as goroutine formal parameters. The compiler catches more mistakes when you write it this way. Happiness!
The simplest answer would be
func addnum(num1, num2, sum chan int) {
n1 := <- num1
n2 := <- num2
sum <- n1 + n2
}
Since you need both num1 and num2 to do the calculation, it makes no sense to do it otherwise. After all, there are two possible execution orders:
num1 generates a number, followed by num2
num2 generates a number, followed by num1
In the first case, our channel reads correspond exactly to the execution order. In the second case, our first read will block until num1 has finally produced a number; the second read will complete near-instantaneous because the num2 channel already has a number.
If you want to know more about channels in Go, I'd suggest to have a look at http://godoc.org/github.com/thomas11/csp -- this is a collection of Hoare's CSP examples written in Go.
To answer the question "Reading from multiple channels simultaneously"
There is a way to listen to multiple channels simultaneously :
func main() {
c1 := make(chan string)
c2 := make(chan string)
...
go func() {
for {
select {
case msg1 := <- c1:
fmt.Println(msg1)
case msg2 := <- c2:
fmt.Println(msg2)
}
}
}()
In this example, I create a channel msg1 and msg2.
Then I create a go routine with an infinite loop. In this loop, I listen to msg1 AND msg2.
This system allow you to read to multiple channels simultaneously and to process the messages when the arrive.
In order to avoid leaks, I should probably add another channel to stop the goroutine.
I need some help and also some insight. This is a program in Ada-2005 which has 3 tasks. The output is 'z'. If the 3 tasks do not happen in the order of their placement in the program then output can vary from z = 2, z = 1 to z = 0 ( That is easy to see in the program, mutual exclusion is attempted to make sure output is z = 2).
WITH Ada.Text_IO; USE Ada.Text_IO;
WITH Ada.Integer_Text_IO; USE Ada.Integer_Text_IO;
WITH System; USE System;
procedure xyz is
x : Integer := 0;
y : Integer := 0;
z : Integer := 0;
task task1 is
pragma Priority(System.Default_Priority + 3);
end task1;
task task2 is
pragma Priority(System.Default_Priority + 2);
end task2;
task task3 is
pragma Priority(System.Default_Priority + 1);
end task3;
task body task1 is
begin
x := x + 1;
end task1;
task body task2 is
begin
y := x + y;
end task2;
task body task3 is
begin
z := x + y + z;
end task3;
begin
Put(" z = ");
Put(z);
end xyz;
I first tried this program
(a) without pragmas, the result : In 100 tries, occurence of 2: 86, occurence of 1: 10, occurence of 0: 4.
Then
(b) with pragmas, the result : In 100 tries, occurence of 2: 84, occurence of 1 : 14, occurence of 0: 2.
Which is unexpected as the 2 results are nearly identical. Which means pragmas or no pragmas the output has same behavior.
Those who are Ada concurrency Gurus please shed some light on this topic. Alternative solutions with semaphores (if possible) is also invited.
Further in my opinion for a critical process (that is what we do with Ada), with pragmas the result should be z = 2, 100% at all times, hence or otherwise this program should be termed as 85% critical !!!! (That should not be so with Ada)
A protected object to do the three operations might look something like this. But note, all this does is make sure that the three variables x, y and z are consistent with the order that the updates occurred in; it says nothing about the order.
protected P is
procedure Update_X;
procedure Update_Y;
procedure Update_Z;
function Get_Z return Integer;
private
X : Integer := 0;
Y : Integer := 0;
Z : Integer := 0;
end P;
protected body P is
procedure Update_X is
begin
X := X + 1;
end Update_X;
procedure Update_Y is
begin
Y := Y + X;
end Update_Y;
procedure Update_Z is
begin
Z := X + Y + Z;
end Update_Z;
function Get_Z return Integer is
begin
return Z;
end Get_Z;
end P;
On the other hand, to make sure that the three tasks "submit their results" in the proper order, you could rewrite P so that a call to say Update_Y will block until Update_X has been called: Get_Z now has to be an entry with an out parameter rather than a function.
protected P is
entry Update_X;
entry Update_Y;
entry Update_Z;
entry Get_Z (Result : out Integer);
private
X_Updated : Boolean := False;
Y_Updated : Boolean := False;
Z_Updated : Boolean := False;
X : Integer := 0;
Y : Integer := 0;
Z : Integer := 0;
end P;
protected body P is
entry Update_X when True is
begin
X := X + 1;
X_Updated := True;
end Update_X;
entry Update_Y when X_Updated is
begin
Y := Y + X;
Y_Updated := True;
end Update_Y;
entry Update_Z when Y_Updated is
begin
Z := X + Y + Z;
Z_Updated := True;
end Update_Z;
entry Get_Z (Result : out Integer) when Z_Updated is
begin
Result := Z;
end Get_Z;
end P;
The three tasks can now have any priority you like. But the task that calls Update_Z will block until the other two have reported.
Well, those pragmas just prioritize the tasks on your system, they don't guarantee any kind of mutual-exclusion on those variables.
There may be some systems where that is enough. However, most Ada implementations these days map Ada tasks to OS threads, and most consumer PC's these days have multiple processors and can spilt their threads among them. There's nothing stopping the OS from scheduling the next lower-priority thread on your second processor while the highest priority thread is running.
This kind of behavior in a program is called a "race condition".
If you want mutual-exlusion on those variables, you need to implement that. Either give control of the variables to one task and use rendezvous to modify them from other tasks, or look into putting them into protected objects. I'd suggest the latter, as rendezvous can be much more difficult to get right. However, if you want to order the calls in a specific way, a master controller task calling rendezvous on the other tasks might be the way to go.
here is a program that is a sequential variant of the above ! .... with just one task (even that can be avoided if I use a single procedure, as suggested by Marc C and T.E.D )
WITH Ada.Text_IO; USE Ada.Text_IO;
WITH Ada.Integer_Text_IO; USE
Ada.Integer_Text_IO;
WITH System; USE System;
procedure xyzsimple is
x : Integer := 0;
y : Integer := 0;
z : Integer := 0;
task type xyz;
T: xyz;
task body xyz is
begin
x:= x + 1;
y:= x + y;
z:= x + y + z;
end xyz;
begin Put(" z = ");
Put(z);
end xyzsimple;
This program always gvies output z = 2, but then it doesn't serve to illustrate what I was trying to do. This program is deterministic, not into the paradigm of concurrency ! Further, this program will never exhibit 'RACE CONDITION' that T.E.D had mentioned.