I'm working through an ebook and here I am doing this code:
func f(n int) {
for i := 0; i < 10; i++ {
fmt.Println(n, ":", i)
amt := time.Duration(rand.Intn(250))
time.Sleep(time.Millisecond * amt)
}
}
func ConcurrMain() {
for i := 0; i < 10; i++ {
go f(i)
}
fmt.Println("hi")
}
The problem is I'm retrieving different values with every run command through goclipse. It seems to work better when i do not execute the sleep command.
In any case, any explanation with step by step i thought would be beneficial in my learning of concurrency
Here's an example of my return value with time sleep:
4 : 0
1 : 0
6 : 0
0 : 0
5 : 0
7 : 0
8 : 0
2 : 0
3 : 0
9 : 0
9 : 1
hi
Then I run it again and I now get with time sleep:
0 : 0
hi
1 : 0
And now a third time and I get with time sleep:
0 : 0
hi
And this time without sleep i get:
1 : 0
1 : 1
1 : 2
1 : 3
1 : 4
1 : 5
1 : 6
1 : 7
1 : 8
3 : 0
3 : 1
4 : 0
4 : 1
4 : 2
9 : 0
6 : 0
6 : 1
6 : 2
2 : 0
2 : 1
2 : 2
2 : 3
2 : 4
2 : 5
2 : 6
2 : 7
2 : 8
2 : 9
7 : 0
7 : 1
7 : 2
7 : 3
7 : 4
7 : 5
7 : 6
5 : 0
5 : 1
5 : 2
5 : 3
5 : 4
5 : 5
5 : 6
5 : 7
5 : 8
5 : 9
9 : 1
1 : 9
8 : 0
3 : 2
hi
I'm using goclipse under windows in case that information is pertinent
UPDATE
It should be noted that this call is called from the main package as:
func main()
{
lab.ConcurrMain()
}
UPDATE2
I added: var wg sync.WaitGroup outside the func scope. I also addedwg.Add(1)inside theConcurrMainmethod just prior togo f(i), then i also addedwg.Wait()just after theforloop which executes the go functionand then finallywg.Done()inside thef()` method **and that seems to work but that answer wasnt in the ebook so i want to understand.
In go, a program is only running for as long as it's main goroutine is running. That is, the goroutine that originally runs the main function, if this exits, the entire program exits.
In the example you've originally given (the code snippets) there's nothing to enforce when the goroutines that you spin up in ConcurrMain will be scheduled and run. Before you added the sync.WaitGroup the main goroutine can exit before the additional goroutines have been scheduled.
If the main goroutine exits, the entire program exits and the other goroutines will not be executed. The main goroutine will not wait for the other goroutines unless you specifically ask it to, with a wait group.
Related
I wonder if I understand correctly the good suffix shift table?
Pattern = GTAGCGGCG
|Pattern| = 9
goodshift[0] : g 1
goodshift[1] : (c)g 2
goodshift[2] : (g)cg 8
goodshift[3] : (g)gcg 3
goodshift[4] : (c)ggcg 8
goodshift[5] : (g)cggcg 8
goodshift[6] : (a)gcggcg 8
goodshift[7] : (t)agcggcg 8
goodshift[8] : (g)tagcggcg 8
Pattern = ABCBAB
|Pattern| = 6
goodshift[0] : b 1
goodshift[1] : (a)b 2
goodshift[2] : (b)ab 4
goodshift[3] : (c)bab 4
goodshift[4] : (b)cbab 4
goodshift[5] : (a)bcbab 4
This question already has answers here:
Why does the capacity of a slice change when you drop the first n items but not the last n items?
(2 answers)
Re-slicing slices in Golang
(2 answers)
Why exactly is there a CAPACITY parameter when creating a slice in Golang
(2 answers)
Decreasing slice capacity
(3 answers)
cap vs len of slice in golang
(3 answers)
Closed 9 months ago.
In the below code:
package main
import "fmt"
func main() {
b := make([]int, 0, 5)
fmt.Println(len(b), cap(b), b) // 0 5
c := b[:3]
fmt.Println(len(c), cap(c), c) // 3 5
d := c[1:5]
fmt.Println(len(d), cap(d), d) // 4 4
e := d[0:4]
fmt.Println(len(e), cap(e), e) // 4 4
}
underlying array for d is same as underlying array for b & c
Why cap(d) is 4?
lets break it down step by step
intialized b
b := make([]int, 0, 5) // which makes [ ] = length 0, with a cap of 5
fmt.Println(len(b), cap(b), b) // 0 5
b => c
c := b[:3] // which makes [ 0 0 0 ] = length 3, still a cap of 5
fmt.Println(len(c), cap(c), c) // 3 5
c => d
d := c[1:5] // which makes [ 0 0 0 0 ] = length of 4, now with a cap of 4
fmt.Println(len(d), cap(d), d) // 4 4
the reason for c[1:5] making the cap one less because it's technically erasing c[0] from the array... it's being completely sliced out of it.
visualization
array of 5
-------------
[ 0 0 0 0 0 ]
0 1 2 3 4
c[1:5] = [ x | 0 0 0 0 ]
^
this index of the array fell behind the sliced indexs and was
sliced out making the new cap is based off the array [ 0 0 0 0 ]
1 2 3 4
why didnt this happen with the others...?
-------------------------------------------
b[:3] = [ 0 0 0 | x x ]
^ ^
these two indexs of the array did not fall behind the
sliced indexs which means the cap remains at 5 [ 0 0 0 x x ]
1 2 3 4 5
for example if n = 2
// Nested loop for all possible pairs
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
// here i have to use, i, j
}
}
for example if n = 3
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
for (int k = 0; k < n; k++)
// here i have to use, i, j, k
But if n = k, then how to iterate n for loops each from 0 to n?
I tried a lot but am not able to come up with a solution.
Is there any way to do it? Please help.
Can you test it with recursive function like this :
int foo(int n, int level)
{
if(level == 0)
{
for(int i=0; i<n; i++){
//Do something
}
return someValue;
}
for(int i=0; i<n; i++){
foo(n, --level);
}
}
//Start it with level = n like this
foo(n,n);
You could use an array for the indexes.
int indexes[n] = {0}; //initialize the whole array to zero
while {
//use indexes[0..n-1] as you would i, j, k, ...
indexes[n-1]++;
//propagate carry
for(i = n-1; i > 0; i--) {
if (indexes[i] == n) {
indexes[i-1]++;
indexes[i] = 0;
}
else break; //early exit from propagation, in case it's not necessary
}
if ( indexes[0] == n) break;
}
We can use the recursive solution ( with only a single loop and rest is the power of recursion ) , you just need to specify the depth and n where:
depth which specifies the level of nested for loops you want to use
n size of each loop
Below is the c++ implementation
#include <iostream>
#include <vector>
using namespace std;
void loop(int n, int depth, vector<int> &iteration){
if(!depth){
for(auto x:iteration)
cout<<x<<" ";
cout<<endl;
return;
}
for(int i=0;i<n;i++){
iteration[iteration.size()-depth] = i;
loop(n, depth-1, iteration);
}
}
int main(int argc, char const *argv[])
{
int depth = 3, n = 5;
vector<int> iteration(depth);
loop(n, depth, iteration);
return 0;
}
Output
0 0 0
0 0 1
0 0 2
0 0 3
0 0 4
0 1 0
0 1 1
0 1 2
0 1 3
0 1 4
0 2 0
0 2 1
0 2 2
0 2 3
0 2 4
0 3 0
0 3 1
0 3 2
0 3 3
0 3 4
0 4 0
0 4 1
0 4 2
0 4 3
0 4 4
1 0 0
1 0 1
1 0 2
1 0 3
1 0 4
1 1 0
1 1 1
1 1 2
1 1 3
1 1 4
1 2 0
1 2 1
1 2 2
1 2 3
1 2 4
1 3 0
1 3 1
1 3 2
1 3 3
1 3 4
1 4 0
1 4 1
1 4 2
1 4 3
1 4 4
2 0 0
2 0 1
2 0 2
2 0 3
2 0 4
2 1 0
2 1 1
2 1 2
2 1 3
2 1 4
2 2 0
2 2 1
2 2 2
2 2 3
2 2 4
2 3 0
2 3 1
2 3 2
2 3 3
2 3 4
2 4 0
2 4 1
2 4 2
2 4 3
2 4 4
3 0 0
3 0 1
3 0 2
3 0 3
3 0 4
3 1 0
3 1 1
3 1 2
3 1 3
3 1 4
3 2 0
3 2 1
3 2 2
3 2 3
3 2 4
3 3 0
3 3 1
3 3 2
3 3 3
3 3 4
3 4 0
3 4 1
3 4 2
3 4 3
3 4 4
4 0 0
4 0 1
4 0 2
4 0 3
4 0 4
4 1 0
4 1 1
4 1 2
4 1 3
4 1 4
4 2 0
4 2 1
4 2 2
4 2 3
4 2 4
4 3 0
4 3 1
4 3 2
4 3 3
4 3 4
4 4 0
4 4 1
4 4 2
4 4 3
4 4 4
Symbolically, you are generating all values of a base-n number of n digits. You perform this by starting from all zeroes and incrementing n^n times. Every time a digit reaches them, you reset it and carry to the next.
E.g. with n=3,
000 001 002 010 011 012 020 021 022 100 101 102 110 111 112 120 121 122 200 201 202 210 211 212 220 221 222
A possible implementation is with n counters.
I've stumbled on a buggy Golang code that was trying to use mutex to prevent changes to the variables printed in a goroutine:
runtime.GOMAXPROCS(1)
mutex := new(sync.Mutex)
for i := 0; i < 10; i++ {
for j := 0; j < 10; j++ {
mutex.Lock()
go func() {
fmt.Println(i, j, i + j);
mutex.Unlock()
}()
}
}
It is clear to me that mutex doesn't lock directly, but on the next iteration, when the value has been incremented already. What is not clear is why j variable reaches 10 according to the output:
...
0 7 7
0 8 8
0 9 9
1 10 11 <--- isn't supposed to be here
...
1 9 10
2 10 12
...
I tried to debug the code and j = 10 is printed when the outer loop for i increments its value. It looks as if the outer loop was releasing the thread allowing goroutine to execute and see invalid value of 10. Could someone clarify this behavior?
You have data races. The results are undefined.
$ go run -race racer.go
==================
WARNING: DATA RACE
Read at 0x00c000016110 by goroutine 7:
main.main.func1()
/home/peter/gopath/racer.go:17 +0x7f
Previous write at 0x00c000016110 by main goroutine:
main.main()
/home/peter/gopath/racer.go:14 +0xf1
Goroutine 7 (running) created at:
main.main()
/home/peter/gopath/racer.go:16 +0xcd
==================
0 1 1
0 2 2
0 3 3
0 4 4
0 5 5
0 6 6
0 7 7
0 8 8
0 9 9
==================
WARNING: DATA RACE
Read at 0x00c000016108 by goroutine 16:
main.main.func1()
/home/peter/gopath/racer.go:17 +0x50
Previous write at 0x00c000016108 by main goroutine:
main.main()
/home/peter/gopath/racer.go:13 +0x140
Goroutine 16 (running) created at:
main.main()
/home/peter/gopath/racer.go:16 +0xcd
==================
1 10 11
1 1 2
1 2 3
1 3 4
1 4 5
1 5 6
1 6 7
1 7 8
1 8 9
1 9 10
2 10 12
2 1 3
2 2 4
2 3 5
2 4 6
2 5 7
2 6 8
2 7 9
2 8 10
2 9 11
3 10 13
3 1 4
3 2 5
3 3 6
3 4 7
3 5 8
3 6 9
3 7 10
3 8 11
3 9 12
4 10 14
4 1 5
4 2 6
4 3 7
4 4 8
4 5 9
4 6 10
4 7 11
4 8 12
4 9 13
5 10 15
5 1 6
5 2 7
5 3 8
5 4 9
5 5 10
5 6 11
5 7 12
5 8 13
5 9 14
6 10 16
6 1 7
6 2 8
6 3 9
6 4 10
6 5 11
6 6 12
6 7 13
6 8 14
6 9 15
7 10 17
7 1 8
7 2 9
7 3 10
7 4 11
7 5 12
7 6 13
7 7 14
7 8 15
7 9 16
8 10 18
8 1 9
8 2 10
8 3 11
8 4 12
8 5 13
8 6 14
8 7 15
8 8 16
8 9 17
9 10 19
9 1 10
9 2 11
9 3 12
9 4 13
9 5 14
9 6 15
9 7 16
9 8 17
9 9 18
Found 2 data race(s)
exit status 66
$
racer.go:
package main
import (
"fmt"
"runtime"
"sync"
)
func main() {
runtime.GOMAXPROCS(1)
mutex := new(sync.Mutex)
for i := 0; i < 10; i++ {
for j := 0; j < 10; j++ {
mutex.Lock()
go func() {
fmt.Println(i, j, i+j)
mutex.Unlock()
}()
}
}
}
Go: Data Race Detector
You have data race, so the results are undefined. Run it with the -race option to see.
When you call mutex.Lock() inside the loop body first, that doesn't block. Then you launch a goroutine that reads i and j and the main goroutine continues to the next iteration of the inner loop, and increments j. Then calls lock again, which will block until the previous goroutine finishes.
But you already have an unsynchronized access (read and write) to j.
Let me to answer why you can get the impossible 10 when print j.
Because when you use goroutine in a loop, fmt.Println(i, j, i+j) race with i++/j++, you cannot determine what value exactly when you print out, and if j increase to the bound, it's possible to print out 10.
if you want to prevent from this race, you can transfer i, j as argument values, e.g.
runtime.GOMAXPROCS(1)
for i := 0; i < 10; i++ {
for j := 0; j < 10; j++ {
go func(a, b, c int) {
fmt.Println(a, b, c);
}(i, j, i+j)
}
}
Hope this helps.
This little code snippet is supposed to loop through a sorted data frame. It keeps a count of how many successive rows have the same information in columns aIndex and cIndex and also bIndex and dIndex. If these are the same, it deposits the count and increments it for the next time around, and if they differ, it deposits the count and resets it to 1 for the next time around.
for (i in 1:nrow(myFrame)) {
if (myFrame[i, aIndex] == myFrame[i, cIndex] &
myFrame[i, bIndex] == myFrame[i, dIndex]) {
myFrame[i, eIndex] <- count
count <- (count + 1)
} else {
myFrame[i, eIndex] <- count
count <- 1
}
}
It's been running for a long time now. I understand that I'm supposed to vectorize whenever possible, but I'm not really seeing it here. What am I supposed to do to make this faster?
Here's what an example few rows should look like after running:
aIndex bIndex cIndex dIndex eIndex
1 2 1 2 1
1 2 1 2 2
1 2 4 8 3
4 8 1 4 1
1 4 1 4 1
I think this will do what you want; the tricky part is that the count resets after the difference, which effectively puts a shift on the eIndex.
There (hopefully) is an easier way to do this, but this is what I came up with.
tmprle <- rle(((myFrame$aIndex == myFrame$cIndex) &
(myFrame$bIndex == myFrame$dIndex)))
myFrame$eIndex <- c(1,
unlist(ifelse(tmprle$values,
Vectorize(seq.default)(from = 2,
length = tmprle$lengths),
lapply(tmprle$lengths,
function(x) {rep(1, each = x)})))
)[-(nrow(myFrame)+1)]
which gives
> myFrame
aIndex bIndex cIndex dIndex eIndex
1 1 2 1 2 1
2 1 2 1 2 2
3 1 2 4 8 3
4 4 8 1 4 1
5 1 4 1 4 1
Maybe this will work. I have reworked the rle and sequence bits.
dat <- read.table(text="aIndex bIndex cIndex dIndex
1 2 1 2
1 2 1 2
1 2 4 8
4 8 1 4
1 4 1 4", header=TRUE, as.is=TRUE,sep = " ")
dat$eIndex <-NA
#identify rows where a=c and b=d, multiply by 1 to get a numeric vector
dat$id<-(dat$aIndex==dat$cIndex & dat$bIndex==dat$dIndex)*1
#identify sequence
runs <- rle(dat$id)
#create sequence, multiply by id to keep only identicals, +1 at the end
count <-sequence(runs$lengths)*dat$id+1
#shift sequence down one notch, start with 1
dat$eIndex <-c(1,count[-length(count)])
dat
aIndex bIndex cIndex dIndex eIndex id
1 1 2 1 2 1 1
2 1 2 1 2 2 1
3 1 2 4 8 3 0
4 4 8 1 4 1 0
5 1 4 1 4 1 1