Why do wait only the first goroutine with
func Sleep(d Duration)
http://golang.org/pkg/time
"Sleep pauses the current goroutine for the duration d."
but the rest is execute directly. I think cause the channel c chan string but i dont understand the behaviour between both.
My Example GoPlayground
All your go routines are running concurrently so they all sleep for 4 seconds at the same time, hence they all end at the same time.
You called them like this. The go means that all the getHostName functions run at once.
for i := 0; i < max; i++ {
go getHostName(haveHost, ipadresse_3, i)
}
And this means that all the sleeps happen at the same time
func getHostName(h chan string, ipAdresse string, n int) {
//Here!!!
time.Sleep(4 * time.Second)
ip := ipAdresse + strconv.Itoa(n)
//ip, ok := net.LookupAddr(ip)
if false {
h <- ip + " - "
} else {
h <- "error" + strconv.Itoa(n)
}
}
So they all finish at the same time.
Related
This is my Snippet Code to run the whole worker
for w := 1; w <= *totalworker; w++ {
wg.Add(1)
go worker(w, jobs, results, dir, &wg)
}
This was my Worker
defer wg.Done()
for j := range jobs {
filename := j[0][4] + ".csv"
fmt.Printf("\nWorker %d starting a job\n", id)
//results <- j //to show The result of jobs, unnecessary
fmt.Printf("\nWorker %d Creating %s.csv\n", id, j[0][4])
CreateFile(dir, &filename, j)
fmt.Printf("\nWorker %d Finished creating %s.csv on %s\n", id, j[0][4], *dir)
fmt.Printf("\nWorker %d finished a job\n", id)
}
}
When i run without WaitGroup it will only create a few of the whole file i needed. but It show the process of it. It show worker1 do job, worker2 do job etc... so until the end of program it will show each of it.
Otherwise, with waitgroup it create the whole file i need. But, its completely do all in one without show the process, show when i run it with WaitGroup it just ended like ... wait where is the whole process xD, it just ended with showing Worker1 do job, worker2 do job etc... at End of program.
Is there any thing i can do with this Waitgroup so it show each of its print?
You need create some channels to listening what previous channel is completed like that, this my example I have 20 routines, they will process some logic at the same time, and return in original order:
package channel
import (
"fmt"
"sync"
"time"
)
func Tests() {
c := make(map[int]chan bool)
var wg sync.WaitGroup
// total go routine
loop := 20
// stop in step
stop := 11
for i := 1; i <= loop; i++ {
// init channel
c[i] = make(chan bool)
}
for i := 1; i <= loop; i++ {
wg.Add(1)
go func(c map[int]chan bool, i int) {
defer wg.Done()
// logic step
fmt.Println("Process Logic step ", i)
if i == 1 {
fmt.Println("Sending message first ", i)
c[i] <- true // send now notify to next step
} else {
select {
case channel := <-c[i-1]:
defer close(c[i-1])
if channel == true {
// send now
fmt.Println("Sending message ", i)
// not sent
if i < loop { // fix deadlock when channel doesnt write
if i == stop && stop > 0 {
c[i] <- false // stop in step i
} else {
c[i] <- true // send now notify to next step
}
}
} else {
// not send
if i < loop { // fix deadlock when channel doesnt write
c[i] <- false
}
}
}
}
}(c, i)
}
wg.Wait()
fmt.Println("go here ")
//time.Sleep(3 * time.Second)go run
fmt.Println("End")
}
I have this sample code, I am facing this synchronisation problem, could anyone please help me how can I achieve that.
package main
import "fmt"
func main() {
baseChan := make(chan int)
go func(bCh chan int){
for {
select{
case stats, _ := <- bCh:
fmt.Println("base stats", stats)
}}
}(baseChan)
second := make(chan int)
go func (sCh chan int) {
fmt.Println("second channel")
for {
select {
case stats, _ := <- sCh:
fmt.Println("seconds stats", stats)
baseChan <- stats
}
}
}(second)
runLoop(second)
}
func runLoop(second chan int) {
for i := 0; i < 5; i++ {
fmt.Println("writing i", i)
second <- i
}
}
actual output:
writing i 0
second channel
seconds stats 0
base stats 0
writing i 1
writing i 2
seconds stats 1
seconds stats 2
I wanted the output to be something like this,
writing i 0
seconds stats 0
base stats 0
writing i 1
seconds stats 1
base stats 1
writing i 2
seconds stats 2
base stats 2
You can write goroutines so that they wait for each other. For instance, here is a mid-level transporter function that sits between a producer and a consumer and forces them to plod along:
func middle(in, out chan int, inAck, outAck chan struct{}) {
defer close(out)
for value := range in {
fmt.Println("middle got", value)
out <- value // send
fmt.Println("middle now waiting for ack from final")
<-outAck // wait for our consumer
inAck <- struct{}{} // allow our producer to continue
}
}
But this is, in a word, dumb. It makes no sense to force the producer to wait until the consumer is done and use channels, because if we want to make the producer wait, we just write:
for ... {
produced_value = producerStep()
final(middle(produced_value))
}
where producerStep() produces the next value, and just dispense with the channels entirely.
Still, here is the complete stepping program on the Go playground.
The code is working as expected. But one thing you can do, put a certain amount interval between two consecutive steps in runLoop() function. But putting a fixed interval is not recommended, you need to write some code to make sure that those jobs are completed. Just showing this example, to show you what is happening here.
func runLoop(second chan int) {
for i := 0; i < 5; i++ {
fmt.Println("writing i", i)
second <- i
time.Sleep(100 * time.Millisecond) // <-- here
}
}
What is happening here? Just giving enough time to complete the jobs that are running in separate goroutines.
Output:
writing i 0
seconds stats 0
base stats 0
writing i 1
seconds stats 1
base stats 1
writing i 2
seconds stats 2
base stats 2
writing i 3
seconds stats 3
base stats 3
writing i 4
seconds stats 4
base stats 4
I have a fairly simple program, which is supposed to self-terminate after a specified duration of time (for example, one second)
The code:
package main
import (
"fmt"
"time"
)
func emit(wordChannel chan string, done chan bool) {
defer close(wordChannel)
words := []string{"The", "quick", "brown", "fox"}
i := 0
t := time.NewTimer(1 * time.Second)
for {
select {
case wordChannel <- words[i]:
i++
if i == len(words) {
i = 0
}
// Please ignore the following case
case <-done:
done <- true
// fmt.Printf("Got done!\n")
close(done)
return
case <-t.C:
fmt.Printf("\n\nGot done!\n\n")
return
}
}
}
func main() {
mainWordChannel := make(chan string)
// Please ignore mainDoneChannel
mainDoneChannel := make(chan bool)
go emit(mainWordChannel, mainDoneChannel)
for word := range mainWordChannel {
fmt.Printf("%s ", word)
}
}
I compile and execute the binary, and you can see the execution here.
That is clearly above 1 second.
Go's documentation on NewTimer reads this:
func NewTimer
func NewTimer(d Duration) *Timer
NewTimer creates a new Timer that will send the current time on its channel after at least duration d.
Can someone kindly help me understand what's happening here? Why isn't the program terminating exactly (or closely at least) after 1 second?
Timer works as intended. It sends a value to a channel.
I think it is useful to read about select statement
Each iteration in your loop can write to a channel.
If > 1 communication can proceed there is no guarantee which are.
So, if add delay to read loop like this :
for word := range mainWordChannel {
fmt.Printf("%s ", word)
time.Sleep(time.Millisecond)
}
In this case, only read from timer.C can proceed. And program will end.
Consider the following code
package main
import (
"fmt"
"runtime"
"sync"
)
func main() {
messages := make(chan bool)
var wg sync.WaitGroup
var x = 1000
wg.Add(runtime.NumCPU())
for i := 0; i < runtime.NumCPU(); i++ {
go func(x int) {
defer wg.Done()
var i = 0
for i < x {
i += 1
fmt.Println(i * i)
}
messages <- true
}(x)
}
go func() {
for i := range messages {
fmt.Println(i)
}
}()
wg.Wait()
}
And the following last couple of line output
980100
982081
984064
true
988036
990025
992016
994009
996004
998001
1000000
Since message <- true is always at the end of a for loop and
for i := range messages {
fmt.Println(i)
}
prints after the channel receive the message.
I expect true to be printed always at the end like
988036
990025
992016
994009
996004
998001
1000000
true
But I find that is only sometimes true, why is that?
What you're doing is:
Start a number of goroutines, equal to the number of CPUs on your system.
Start one additional goroutine, which reads and prints the values from the messages channel.
Wait for the goroutines from #1 to terminate
Exit
Because you're only waiting for the first batch of goroutines to terminate, there is no guarantee that all (or even any) of the messages values will be printed before the program terminates.
var m *sync.RWMutex
func main() {
m = new(sync.RWMutex)
n := 100
go func() {
for i := 0; i < n; i++ {
write("WA", i)
}
}()
go func() {
for i := 0; i < n; i++ {
write("WB", i)
}
}()
select {}
}
func write(tag string, i int) {
m.Lock()
fmt.Printf("[%s][%s%d]write start \n", tag, tag, i)
time.Sleep(100 * time.Millisecond)
fmt.Printf("[%s][%s%d]write end \n", tag, tag, i)
m.Unlock()
// time.Sleep(1 * time.Millisecond)
}
Result in console:
go run mutex.go
[WB][WB0]write start
[WB][WB0]write end
[WB][WB1]write start
[WB][WB1]write end
[WB][WB2]write start
[WB][WB2]write end
[WB][WB3]write start
[WB][WB3]write end
[WB][WB4]write start
[WB][WB4]write end
[WB][WB5]write start
[WB][WB5]write end
[WB][WB6]write start
[WB][WB6]write end
[WB][WB7]write start
[WB][WB7]write end
[WB][WB8]write start
[WB][WB8]write end
[WB][WB9]write start
[WB][WB9]write end
...
> go version
go version go1.5.2 windows/amd64
The question is:
why there is no chance for the go-routine of "[WA]"?
Why the mutex code stops another whole go-routine?
I know there must be a story or a theory about it.
Please give me a url to read and study.
Go uses cooperative multitasking; it doesn't use preemptive mutitasking: Computer multitasking. You need to give the scheduler an opportunity to run between locks. For example, by a call to Gosched(),
package main
import (
"fmt"
"runtime"
"sync"
"time"
)
var m *sync.RWMutex
func main() {
m = new(sync.RWMutex)
n := 100
go func() {
for i := 0; i < n; i++ {
write("WA", i)
}
}()
go func() {
for i := 0; i < n; i++ {
write("WB", i)
}
}()
select {}
}
func write(tag string, i int) {
m.Lock()
fmt.Printf("[%s][%s%d]write start \n", tag, tag, i)
time.Sleep(100 * time.Millisecond)
fmt.Printf("[%s][%s%d]write end \n", tag, tag, i)
m.Unlock()
runtime.Gosched()
}
Output:
[WB][WB0]write start
[WB][WB0]write end
[WA][WA0]write start
[WA][WA0]write end
[WB][WB1]write start
[WB][WB1]write end
[WA][WA1]write start
[WA][WA1]write end
[WB][WB2]write start
[WB][WB2]write end
[WA][WA2]write start
[WA][WA2]write end
[WB][WB3]write start
[WB][WB3]write end
[WA][WA3]write start
[WA][WA3]write end
This situation is called live lock.
When you call m.Unlock() even though two goroutines (A and B) are waiting for this lock to be released the scheduler is free to wake up any of them to proceed.
It looks like the current implementation of scheduler in Go doesn't switch to goroutine A fast to enough for it to acquire the mutex. Before this happens goroutine B re-acquires the mutex.
As you probably found out if you move time.Sleep call after m.Unlock call both A and B goroutines will be running concurrently.
Hopefully this makes sense.
#peterSO 's answer is correct. Just to elaborate a bit on scheduling, that for loop is a sequential tight loop. Means that the compiled instructions from that loop, would occupy a whole thread to finish. Meanwhile other bits of low level instructions would block unless they have some schedule cycles provided by runtime.Gosched() or sleep, in the middle of the loop. That's why they actually have not a chance to catch on with the sync.Mutex (BTW both should be sync.Mutex at declaration and instantiation):
go func() {
for i := 0; i < n; i++ {
runtime.Gosched()
write("WA", i)
}
}()
go func() {
for i := 0; i < n; i++ {
runtime.Gosched()
write("WB", i)
}
}()
And Go scheduler is not preemptive at instruction level (like Erlang). That's why it's better to orchestrate execution path using channels.
Note: I've learnt this the hard way (not a low-level Go compiler expert). And channels provide that orchestration on Go-Routines (& those extra cycles) in a more clean manner. In other words sync.Mutex should be used just for supervising access to stuff; not for orchestration.