I want to write three concurrent go routines that sends integers to each other. Now, my code is compiled properly, however after first execution it gives error "throw: all goroutines are asleep - deadlock!". I tried to find the error but I could not able to find any error in code logic.Can anybody help me to find the mistake with my code. My code is given below.
package main
import "rand"
func Routine1(command12 chan int, response12 chan int, command13 chan int, response13 chan int) {
// z12 is a variable which stores the value comming from channel 2 and z13 is a variable which stores the value comming from channel 3.
z12 := 200
z13 := 200
m12 := false
m13 := false
y := 0
for i := 0; i < 20; i++ {
y = rand.Intn(100)
// If y's value is not 0 then the value will be sent to routine 2 or 3 according to prime or not.
// If y's value is 0 then process state (the varibles used by it means z12, z13) and channel state will be saved.[routine 1 is initiator]
if y == 0 {
print(z12, " z12 STATE SAVED
")
print(z13, " z13 STATE SAVED
")
// Routine 1 is initiator, it sends 0 to make other process to save the state.
y = 0
command12 <- y
command13 <- y
// Untill routine 2 and 3 does not send 0, process 1 is on channel saving state (it's process state is already saved).
// When routine 1 recives 0 from both other processes, channel is saved and routine 1 retuns to it's common routine procedure.
// When routine 1 recives 0 from any other processes, saving channel bettwen them is stopped.
// m12, m13 is used to mark whether 0 recived or not.
for m12 != true || m13 != true {
select {
case cmd1 := <-response12:
{
z12 = cmd1
if z12 != 0 {
print(z12, " z12 Channel Saving....
")
y = rand.Intn(100)
command12 <- y
}
if z12 == 0 {
m12 = true
print(" z12 Channel Saving Stopped
")
}
}
case cmd2 := <-response13:
{
z13 = cmd2
if z13 != 0 {
print(z13, " z13 Channel Saving....
")
y = rand.Intn(100)
command13 <- y
}
if z13 == 0 {
m13 = true
print(" z13 Channel Saving Stopped
")
}
}
}
}
// After saving process state it retuns to it's normal behaviour.
m12 = false
m13 = false
}
if y != 0 {
// If y value is not 0, routine 1 just sends int to other process according to prime or not and recives int accordingly.
if y%2 == 0 {
command12 <- y
}
if y%2 != 0 {
command13 <- y
}
select {
case cmd1 := <-response12:
{
z12 = cmd1
print(z12, " z12
")
}
case cmd2 := <-response13:
{
z13 = cmd2
print(z13, " z13
")
}
}
}
}
close(command12)
close(command13)
}
//Routine 2 (or 3) is not an initiator (means it can't send 0). When it recives 0 (from routine 1 or 3) it save the state of process and the state of the channel from which it recived).
// When it recives 0 from both other two routine, it saves all channel state and returns to it's common behaviour. [same in routine 3]
func Routine2(command12 chan int, response12 chan int, command23 chan int, response23 chan int) {
z21 := 200
z23 := 200
m21 := false
m23 := false
for i := 0; i < 20; i++ {
select {
case x, open := <-command12:
{
if !open {
return
}
if x != 0 && m23 != true {
z21 = x
print(z21, " z21
")
}
if x != 0 && m23 == true {
z21 = x
print(z21, " z21 Channel Saving
")
}
if x == 0 {
m21 = true
if m21 == true && m23 == true {
print(" z21 and z23 Channel Saving Stopped
")
m23 = false
m21 = false
}
if m21 == true && m23 != true {
z21 = x
print(z21, " z21 Channel Saved
")
}
}
}
case x, open := <-response23:
{
if !open {
return
}
if x != 0 && m21 != true {
z23 = x
print(z23, " z21
")
}
if x != 0 && m21 == true {
z23 = x
print(z23, " z23 Channel Saving
")
}
if x == 0 {
m23 = true
if m21 == true && m23 == true {
print(" z23 Channel Saving Stopped
")
m23 = false
m21 = false
}
if m23 == true && m21 != true {
z23 = x
print(z23, " z23 Channel Saved
")
}
}
}
}
if m23 == false && m21 == false {
y := rand.Intn(100)
if y%2 == 0 {
if y == 0 {
y = 10
response12 <- y
}
}
if y%2 != 0 {
if y == 0 {
y = 10
response23 <- y
}
}
}
if m23 == true && m21 != true {
y := rand.Intn(100)
response12 <- y
}
if m23 != true && m21 == true {
y := rand.Intn(100)
command23 <- y
}
}
close(response12)
close(command23)
}
func Routine3(command13 chan int, response13 chan int, command23 chan int, response23 chan int) {
z31 := 200
z32 := 200
m31 := false
m32 := false
for i := 0; i < 20; i++ {
select {
case x, open := <-command13:
{
if !open {
return
}
if x != 0 && m32 != true {
z31 = x
print(z31, " z21
")
}
if x != 0 && m32 == true {
z31 = x
print(z31, " z31 Channel Saving
")
}
if x == 0 {
m31 = true
if m31 == true && m32 == true {
print(" z21 Channel Saving Stopped
")
m31 = false
m32 = false
}
if m31 == true && m32 != true {
z31 = x
print(z31, " z31 Channel Saved
")
}
}
}
case x, open := <-command23:
{
if !open {
return
}
if x != 0 && m31 != true {
z32 = x
print(z32, " z32
")
}
if x != 0 && m31 == true {
z32 = x
print(z32, " z32 Channel Saving
")
}
if x == 0 {
m32 = true
if m31 == true && m32 == true {
print(" z32 Channel Saving Stopped
")
m31 = false
m32 = false
}
if m32 == true && m31 != true {
z32 = x
print(z32, " z32 Channel Saved
")
}
}
}
}
if m31 == false && m32 == false {
y := rand.Intn(100)
if y%2 == 0 {
response13 <- y
}
if y%2 != 0 {
response23 <- y
}
}
if m31 == true && m32 != true {
y := rand.Intn(100)
response13 <- y
}
if m31 != true && m32 == true {
y := rand.Intn(100)
response23 <- y
}
}
close(response13)
close(response23)
}
func main() {
// Three concurrent channels are created to pass integers to each other.
// command 12 used to send int and response12 is used to receive int from routine 1 to routine 2.
// response 12 used to send int and command 12 is used to receive int from routine 2 to routine 1. {so as for others}
command12 := make(chan int)
response12 := make(chan int)
command13 := make(chan int)
response13 := make(chan int)
command23 := make(chan int)
response23 := make(chan int)
go Routine1(command12, response12, command13, response13)
go Routine2(command12, response12, command23, response23)
Routine3(command13, response13, command23, response23)
}