fmt.Println is not executing in order when used without sleep - go

I'm trying to understand, why my code doesn't behave as I expect it. The problem is that I would expect, that my code would behave like that:
Define channel
Run goroutine and start looping
Put value into channel, print "finished"
Starting second iteration, blocking call(there is already value in the channel), move to main goroutine
Printing 1, trying to run second iteration, blocking call for main goroutine, coming back to second goroutine
Cycle repeats
It works like that, but only with time.Sleep, but for some reason when commenting out time.Sleep it behaves totally different. What's even more interesting that sometimes for really small values of time like Nanos etc this code returns even more different results. Could someone explain me, why it works like that? My guess is that maybe Println is too slow on display, but it sounds weird to me..
Thanks
** As expected: **
finished
1
finished
2
finished
3
finished
6
finished
4
finished
8
finished all
** Not expected **
finished
1
2
finished
finished
3
finished
6
4
finished
finished
8
finished all
func main() {
var c chan int = make(chan int)
go sendingThrowingResults(c)
for val := range c {
fmt.Println(val)
}
fmt.Println("finished all")
}
func sendingThrowingResults(c chan int) {
var results []int = []int{1, 2, 3, 6, 4, 8}
for _, val := range results {
//time.Sleep(100 * time.Millisecond)
c <- val
fmt.Println("finished")
}
defer close(c)
}

A channel operation needs both sides to participate. A write only happens when a reader is ready. Once that happens, there is no guarantee on which goroutine will run first.
Thus, once the channel write happens, one of the two printlns will work, in some random order.

Related

Doesn't go routine and the channels work in order of call?

Doesn't go routine and the channels worked in the order they were called.
and go routine share values between the region variables?
main.go
var dataSendChannel = make(chan int)
func main() {
a(dataSendChannel)
time.Sleep(time.Second * 10)
}
func a(c chan<- int) {
for i := 0; i < 1000; i++ {
go b(dataSendChannel)
c <- i
}
}
func b(c <-chan int) {
val := <-c
fmt.Println(val)
}
output
> go run main.go
0
1
54
3
61
5
6
7
8
9
Channels are ordered. Goroutines are not. Goroutines may run, or stall, more or less at random, whenever they are logically allowed to run. They must stop and wait whenever you force them to do so, e.g., by attempting to write on a full channel, or using a mutex.Lock() call on an already-locked mutex, or any of those sorts of things.
Your dataSendChannel is unbuffered, so an attempt to write to it will pause until some goroutine is actively attempting to read from it. Function a spins off one goroutine that will attempt one read (go b(...)), then writes and therefore waits for at least one reader to be reading. Function b immediately begins reading, waiting for data. This unblocks function a, which can now write some integer value. Function a can now spin off another instance of b, which begins reading; this may happen before, during, or after the b that got a value begins calling fmt.Println. This second instance of b must now wait for someone—which in this case is always function a, running the loop—to send another value, but a does that as quickly as it can. The second instance of b can now begin calling fmt.Println, but it might, mostly-randomly, not get a chance to do that yet. The first instance of b might already be in fmt.Println, or maybe it isn't yet, and the second one might run first—or maybe both wait around for a while and a third instance of b spins up, reads some value from the channel, and so on.
There's no guarantee which instance of b actually gets into fmt.Println when, so the values you see printed will come out in some semi-random order. If you want the various b instances to sequence themselves, they will need to do that somehow.

Why doesn't this buffered channel block in my code?

I'm learning the Go language. Can someone please explain the output here?
package main
import "fmt"
var c = make(chan int, 1)
func f() {
c <- 1
fmt.Println("In f()")
}
func main() {
go f()
c <- 2
fmt.Println(<-c)
fmt.Println(<-c)
}
Output:
In f()
2
1
Process finished with exit code 0
Why did "In f()" occur before "2"? If "In f()" is printed before "2", the buffered channel should block. But this didn't happen, why?
The other outputs are reasonable.
Image of my confusing result
The order of events that cause this to run through are these:
Trigger goroutine.
Write 2 to the channel. Capacity of the channel is now exhausted.
Read from the channel and output result.
Write 1 to the channel.
Read from the channel and output result.
The order of events that cause this to deadlock are these:
Trigger goroutine.
Write 1 to the channel. Capacity of the channel is now exhausted.
Write 2 to the channel. Since the channel's buffer is full, this blocks.
The output you provide seems to indicate that the goroutine finishes first and the program doesn't deadlock, which contradicts above two scenarios as explanation. Here's what happens though:
Trigger goroutine.
Write 2 to the channel.
Read 2 from the channel.
Write 1 to the channel.
Output In f().
Output the 2 received from the channel.
Read 1 from the channel.
Output the 1 received from the channel.
Keep in mind that you don't have any guarantees concerning the scheduling of goroutines unless you programmatically enforce them. When you start a goroutine, it is undefined when the first code of that goroutine are actually executed and how much the starting code progresses until then. Note that since your code relies on a certain order of events, it is broken by that definition, just to say that explicitly.
Also, at any point in your program, the scheduler can decide to switch between different goroutines. Even the single line fmt.Printtln(<-c) consists of multiple steps and in between each step the switch can occur.
To reproduce block you have to run that code many times the easiest way to do it with test. You don't have block cause of luck. But it is not guaranteed:
var c = make(chan int, 1)
func f() {
c <- 1
fmt.Println("In f()")
}
func TestF(t *testing.T) {
go f()
c <- 2
fmt.Println(<-c)
fmt.Println(<-c)
}
and run with command:
go test -race -count=1000 -run=TestF -timeout=4s
where count number of tests. It reproduces blocking to me.
Provide timeout to not wait default 10 minutes

Go goroutines leaking

Following this post about go-routines leaking, https://www.ardanlabs.com/blog/2018/11/goroutine-leaks-the-forgotten-sender.html, i tried to solve my leaking code. But adding a buffer to the channel it did not do the trick.
My code
package main
import (
"fmt"
"runtime"
"time"
)
func main() {
fmt.Println(runtime.NumGoroutine())
leaking()
time.Sleep(5)
fmt.Println(runtime.NumGoroutine())
}
func leaking() {
errChang := make(chan int, 1)
go func() {
xx := return666()
errChang <- xx
}()
fmt.Println("hola")
return
fmt.Println(<-errChang)
}
func return666() int {
time.Sleep(time.Second * 1)
return 6
}
My initial code did not use a buffer, leading to the go-routine in the leaking function, .. to leak. Following the post i expected that by adding a buffer to the channel, it would have avoided leaking.
Here, in the Go Playground, is your original code with a few slight modifications:
the delays are reduced, except for time.Sleep(5) which becomes time.Sleep(time.Second);
a return is removed because it becomes unnecessary;
a fmt.Println is commented out, because with both the return and the uncommented fmt.Println, go vet complains about the unreachable fmt.Println;
the channel stored in errChang is changed to unbuffered.
When run, its output is:
1
hola
2
(with a small delay before the 2), showing that indeed, the anonymous goroutine you started in function leaking is still running.
If we uncomment the commented-out fmt.Println, the output is:
1
hola
6
1
(with the same slight delay before the final 1) because we now wait for (and then print) the value computed in return666 and sent over channel errChang.
If we keep the commented-out fmt.Println commented out and make the channel buffered, the output becomes:
1
hola
1
as the anonymous goroutine is now able to push its value (6) into the channel.
The channel itself would be garbage collected, along with the single value stored inside it, as there are no remaining references to the channel at this point. Note, however, that simply making the channel buffered is not always sufficient. If we send two values down the channel, the program returns to printing:
1
hola
2
as the anonymous goroutine succeeds in putting 6 into the channel but then blocks trying to put 42 in as well.

Golang concurrency and blocking with a single channel, explanation needed

I'm playing around with the code presented on https://tour.golang.org/concurrency/5. My idea was that I could simplify the code by getting rid of the quit channel and still keep the correct program behavior - just for learning purposes.
Here is the code I've got (simplified it even more for better readability):
package main
import "fmt"
import "time"
func sendNumbers(c chan int) {
for i := 0; i < 2; i++ {
c <- i
}
}
func main() {
c := make(chan int)
go func() {
for i := 0; i < 2; i++ {
fmt.Println(<-c)
}
}()
time.Sleep(0 * time.Second)
sendNumbers(c)
}
In this code, the go routine I spawn should be able to receive 2 numbers before it returns. The sendNumbers() function I call next sends exactly 2 numbers to the channel c.
So, the expected output of the program is 2 lines: 0 and 1. However, what I'm getting when I run the code on the page, is just a single line containing 0.
Note the
time.Sleep(0 * time.Second)
though that I deliberately added before calling sendNumbers(c). If I change it to
time.Sleep(1 * time.Second)
The output becomes as expected:
0
1
So, I'm confused with what happens. Can someone explain what is going on? Shouldn't both sends and receives block regardless of how much time is passed before I call sendNumbers()?
In Go, the program exits as soon as the main function returns regardless of whether other goroutines are still running or not. If you want to make sure the main function does not exit prematurely, you need some synchronization mechanism. https://nathanleclaire.com/blog/2014/02/15/how-to-wait-for-all-goroutines-to-finish-executing-before-continuing/
You don’t absolutely have to use synchronization primitives, you could also do it with channels only, arguably a more idiomatic way to do it.

Mutual Exclusion of Concurrent Goroutines

In my code there are three concurrent routines. I try to give a brief overview of my code,
Routine 1 {
do something
*Send int to Routine 2
Send int to Routine 3
Print Something
Print Something*
do something
}
Routine 2 {
do something
*Send int to Routine 1
Send int to Routine 3
Print Something
Print Something*
do something
}
Routine 3 {
do something
*Send int to Routine 1
Send int to Routine 2
Print Something
Print Something*
do something
}
main {
routine1
routine2
routine3
}
I want that, while codes between two do something (codes between two star marks) is executing, flow of control must not go to other goroutines. For example, when routine1 is executing the events between two stars (sending and printing events), routine 2 and 3 must be blocked (means flow of execution does not pass to routine 2 or 3 from routine 1). After completing last print event, flow of execution may pass to routine 2 or 3. Can anybody help me by specifying, how can I achieve this ? Is it possible to implement above specification by WaitGroup ? Can anybody show me by giving a simple example how to implement above specified example by using WaitGroup. Thanks.
NB: I give two sending and two printing options, in fact there is lots of sending and printing.
If I have gotten it correctly, what you want is to prevent simultaneous execution of some part of each function and other functions. The following code does this: fmt.Println lines won't happen as other routines are running. Here's what happens: when execution gets to the print section, it waits until other routines end, if they are running, and while this print line is executing other routines don't start and wait. I hope that is what you are looking for. Correct me if I'm wrong about this.
package main
import (
"fmt"
"rand"
"sync"
)
var (
mutex1, mutex2, mutex3 sync.Mutex
wg sync.WaitGroup
)
func Routine1() {
mutex1.Lock()
// do something
for i := 0; i < 200; i++ {
mutex2.Lock()
mutex3.Lock()
fmt.Println("value of z")
mutex2.Unlock()
mutex3.Unlock()
}
// do something
mutex1.Unlock()
wg.Done()
}
func Routine2() {
mutex2.Lock()
// do something
for i := 0; i < 200; i++ {
mutex1.Lock()
mutex3.Lock()
fmt.Println("value of z")
mutex1.Unlock()
mutex3.Unlock()
}
// do something
mutex2.Unlock()
wg.Done()
}
func Routine3() {
mutex3.Lock()
// do something
for i := 0; i < 200; i++ {
mutex1.Lock()
mutex2.Lock()
fmt.Println("value of z")
mutex1.Unlock()
mutex2.Unlock()
}
// do something
mutex3.Unlock()
wg.Done()
}
func main() {
wg.Add(3)
go Routine1()
go Routine2()
Routine3()
wg.Wait()
}
UPDATE: Let me explain these three mutex here: a mutex is, as documentation says: "a mutual exclusion lock." That means when you call Lock on a mutex your code just waits there if somebody else have locked the same mutex. Right after you call Unlock that blocked code will be resumed.
Here I put each function in its own mutex by locking a mutex at the beginning of the function and unlocking it the end. By this simple mechanism you can avoid running any part of code you want at the same time as those functions. For instance, everywhere you want to have a code that should not be running when Routine1 is running, simply lock mutex1 at the beginning of that code and unlock at at the end. That is what I did in appropriate lines in Routine2 and Routine3. Hope that clarifies things.
You could use sync.Mutex. For example everything between im.Lock() and im.Unlock() will exclude the other goroutine.
package main
import (
"fmt"
"sync"
)
func f1(wg *sync.WaitGroup, im *sync.Mutex, i *int) {
for {
im.Lock()
(*i)++
fmt.Printf("Go1: %d\n", *i)
done := *i >= 10
im.Unlock()
if done {
break
}
}
wg.Done()
}
func f2(wg *sync.WaitGroup, im *sync.Mutex, i *int) {
for {
im.Lock()
(*i)++
fmt.Printf("Go2: %d\n", *i)
done := *i >= 10
im.Unlock()
if done {
break
}
}
wg.Done()
}
func main() {
var wg sync.WaitGroup
var im sync.Mutex
var i int
wg.Add(2)
go f1(&wg, &im, &i)
go f2(&wg, &im, &i)
wg.Wait()
}
Another way would be to have a control channel, with only one goroutine allowed to execute at any one time, with each routine sending back to the 'control lock' whenever they are done doing their atomic operation:
package main
import "fmt"
import "time"
func routine(id int, control chan struct{}){
for {
// Get the control
<-control
fmt.Printf("routine %d got control\n", id)
fmt.Printf("A lot of things happen here...")
time.Sleep(1)
fmt.Printf("... but only in routine %d !\n", id)
fmt.Printf("routine %d gives back control\n", id)
// Sending back the control to whichever other routine catches it
control<-struct{}{}
}
}
func main() {
// Control channel is blocking
control := make(chan struct{})
// Start all routines
go routine(0, control)
go routine(1, control)
go routine(2, control)
// Sending control to whichever catches it first
control<-struct{}{}
// Let routines play for some time...
time.Sleep(10)
// Getting control back and terminating
<-control
close(control)
fmt.Println("Finished !")
}
This prints:
routine 0 got control
A lot of things happen here...... but only in routine 0 !
routine 0 gives back control
routine 1 got control
A lot of things happen here...... but only in routine 1 !
routine 1 gives back control
routine 2 got control
A lot of things happen here...... but only in routine 2 !
routine 2 gives back control
routine 0 got control
A lot of things happen here...... but only in routine 0 !
routine 0 gives back control
routine 1 got control
A lot of things happen here...... but only in routine 1 !
routine 1 gives back control
routine 2 got control
A lot of things happen here...... but only in routine 2 !
routine 2 gives back control
routine 0 got control
A lot of things happen here...... but only in routine 0 !
routine 0 gives back control
routine 1 got control
A lot of things happen here...... but only in routine 1 !
routine 1 gives back control
routine 2 got control
A lot of things happen here...... but only in routine 2 !
routine 2 gives back control
routine 0 got control
A lot of things happen here...... but only in routine 0 !
routine 0 gives back control
routine 1 got control
A lot of things happen here...... but only in routine 1 !
routine 1 gives back control
routine 2 got control
A lot of things happen here...... but only in routine 2 !
routine 2 gives back control
Finished !
You are asking for a library function that explicitly stop other routines ? Make it clear that, it is not possible in Go and also for most other languages. And sync, mutex case is not possible for your case.

Resources