Something bizarre happened in CGO. My new code started the anonymous
goroutine to receive first but it does not sleep below the goroutine and
jumps to end the function. So I  returned to the sending before receiving
way, which guaranteed the program's safety.

There ain't always one way that fits all.  Sometimes a public variable is
better than a channel.
Knowing the boundaries of your tool is always better than believing it will
always prevail.

*Blocking on send until the channel is ready is exactly what is required
normally.*
* " Are you suggesting something else should happen? If so, what exactly?"*

Beyond the cgo accident, Here is one scenario:

When one server finds something wrong, it sends out a request to another
server for help.
Then it makes a log and then a ticker to recheck the situation again and
again and in the meantime, to receive a response from that server that
indicates everything is fine.

So here is a gap between sending help and getting ready to receive the "ok"
response. It is a tiny gap but it is not possible that the other server
sends the "ok" message back through TCP connection just in this gap. Yes my
program handles the TCP message as always, in this case sends back through
the channel to the goroutine that has not prepared the select for ticker
channel and  ok-receiving channel. Uh-oh, deadlock, crash! What is your
suggestion? buffered channel? In this case you already admit that
opportunity that the sending happens when the receiver is not ready.

On Thu, Apr 14, 2022 at 3:40 PM Brian Candler <b.cand...@pobox.com> wrote:

> The fact that the sender may have to wait does not by itself make a
> "deadlock".
>
> It's a deadlock if the sender blocks and, due to poor programming, the
> receiver is *never* ready to receive. That's a problem with your software,
> not with Go's concept of channels.
>
> Blocking on send until the channel is ready is exactly what is required
> normally. Are you suggesting something else should happen? If so, what
> exactly?
>
> This is well worth watching:
> Rethinking Classical Concurrency Patterns (Bryan C. Mills)
> https://www.youtube.com/watch?v=5zXAHh5tJqQ
>
> On Thursday, 14 April 2022 at 02:55:56 UTC+1 yan.z...@gmail.com wrote:
>
>> You are right, Brian.
>> The difference is not whether the channel is buffered or unbuffered -
>> while the receiver is present, none will encounter the deadlock.
>>
>> package main
>>
>> import (
>>     "fmt"
>>     "time"
>>     )
>>
>> //var c = make(chan int)
>> var c = make(chan int, 2)
>>
>> func report(){
>>     for{
>>         select{
>>         case n:= <- c:
>>             fmt.Println(n, time.Now().Format("2006-01-02 15:04:05"))
>>         default:
>>             time.Sleep(time.Second)
>>         }
>>     }
>> }
>>
>> func main() {
>>
>>     go report()
>>
>>     for i:=1; i<=5; i++{
>>         c <- i
>>     }
>>
>> }
>>
>> But obviously, the buffered channel provides another layer of support in
>> case the receiver is temporarily absent:
>>
>> package main
>>
>> import (
>>     "fmt"
>>     "time"
>>     )
>>
>> //var c = make(chan int)
>> var c = make(chan int, 5)
>>
>> func report(){
>>     for{
>>         select{
>>         case n:= <- c:
>>             fmt.Println(n, time.Now().Format("2006-01-02 15:04:05"))
>>         default:
>>             time.Sleep(time.Second)
>>         }
>>     }
>> }
>>
>> func main() {
>>
>>     for i:=1; i<=5; i++{
>>         c <- i
>>     }
>>
>>     report()
>>
>> }
>>
>>
>> > I made up a work around that just dumps the new message if the buffer
>>> is full:
>>>
>>> You don't need to do that: use select { ... } to check if the channel is
>>> ready to receive or not.
>>> https://go.dev/play/p/Mb7VVCTvnfk
>>>
>>> But in practice, this is almost never needed, because one goroutine is
>>> doing the sending and a different goroutine is doing the receiving.  The
>>> sending goroutine blocks until the receiver is ready.
>>>
>>> On Wednesday, 13 April 2022 at 09:40:22 UTC+1 yan.z...@gmail.com wrote:
>>>
>>>> Since I found if inserting into a buffered channel could cause a crash
>>>> if it is full already
>>>> ( now I only use unbuffered channels in work)
>>>> https://groups.google.com/g/golang-nuts/c/U8lz6noKkuA
>>>>
>>>> package main
>>>>
>>>> var c = make(chan int, 1)
>>>>
>>>> func main() {
>>>>
>>>>     c <- 1
>>>>     c <- 2 //fatal error: all goroutines are asleep - deadlock!
>>>>     c <- 3
>>>>
>>>> }
>>>>
>>>> I made up a work around that just dumps the new message if the buffer
>>>> is full:
>>>>
>>>> package main
>>>>
>>>> import (
>>>>     "fmt"
>>>>     "sync"
>>>>     )
>>>>
>>>> type ChanInt struct{
>>>>     Ch chan int
>>>>     Mu *sync.Mutex
>>>> }
>>>>
>>>> var c = ChanInt{make(chan int, 1), new(sync.Mutex)}
>>>>
>>>> func (ch ChanInt) Fill(k int){
>>>>     ch.Mu.Lock()
>>>>     defer ch.Mu.Unlock()
>>>>
>>>>     if len(ch.Ch) < cap(ch.Ch){
>>>>         ch.Ch <- k
>>>>     }
>>>> }
>>>>
>>>> func main() {
>>>>
>>>>     fmt.Println("Channel Status: ",len(c.Ch), cap(c.Ch))
>>>>     c.Fill(5)
>>>>     fmt.Println("Channel Status: ", len(c.Ch), cap(c.Ch))
>>>>     fmt.Println("get one out of Channel:", <-c.Ch)
>>>>     fmt.Println("Channel Status: ", len(c.Ch), cap(c.Ch))
>>>>
>>>>     c.Fill(6)
>>>>     // c.Ch <- 7 //fatal error: all goroutines are asleep - deadlock!
>>>>     c.Fill(7)
>>>>     fmt.Println("Channel Status: ", len(c.Ch), cap(c.Ch))
>>>>     fmt.Println("get one out of Channel:", <-c.Ch)
>>>> }
>>>>
>>> --
>>> You received this message because you are subscribed to a topic in the
>>> Google Groups "golang-nuts" group.
>>> To unsubscribe from this topic, visit
>>> https://groups.google.com/d/topic/golang-nuts/6ExktXrF5Xc/unsubscribe.
>>> To unsubscribe from this group and all its topics, send an email to
>>> golang-nuts...@googlegroups.com.
>>> To view this discussion on the web visit
>>> https://groups.google.com/d/msgid/golang-nuts/7df07f32-d7aa-45db-91d6-de75e18ad8d8n%40googlegroups.com
>>> <https://groups.google.com/d/msgid/golang-nuts/7df07f32-d7aa-45db-91d6-de75e18ad8d8n%40googlegroups.com?utm_medium=email&utm_source=footer>
>>> .
>>>
>> --
> You received this message because you are subscribed to a topic in the
> Google Groups "golang-nuts" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/d/topic/golang-nuts/6ExktXrF5Xc/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to
> golang-nuts+unsubscr...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/golang-nuts/0c91adbb-94c7-4475-891d-3c4bb3d4e80dn%40googlegroups.com
> <https://groups.google.com/d/msgid/golang-nuts/0c91adbb-94c7-4475-891d-3c4bb3d4e80dn%40googlegroups.com?utm_medium=email&utm_source=footer>
> .
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/CADEX6_WZcpOQaTRUYqA8WKGiSUT1-EtCD5gcfYRzE9L%2BxfU54Q%40mail.gmail.com.

Reply via email to