-3

In C# when we want to cause delay between the execution of two procedures we have two options:

  1. Thread.Sleep(time) which is blocking
  2. await Task.Delay(time) which is non-blocking

In other words, Thread.Sleep(time) blocks the current thread for the specified time while await Task.Delay(time) suspends the executing thread (allowing the OS thread scheduler to select and run more threads) and then it resumes it after the specified time.

In Go, there is time.Sleep(time) method which is known to be a blocking method. Being new to Go, I have this question, assuming I have a thousand of go routines (since go has it's own thread scheduler instead of relying on the OS scheduler, this should not be a problem) and I would like to implement a retry pattern in each one of these go routines in such a way that:

FOR 5 Times {
   IF Request Fails 
      THEN
          time.Sleep(time.Second * 30)
   ELSE
      RETURN
}

Would it be safe to use time.Sleep(time) in this case? Or is there a better way?

Edit: I am not asking if time.Sleep(time) is blocking!! I have no I idea why my question is duplicate of that post!

Arnold Zahrneinder
  • 4,788
  • 10
  • 40
  • 76
  • 1
    "Would it be safe to use time.Sleep(time) in this case?" What is "save" here? Asked differently: What do you consider "unsafe"? What type of problem do you anticipate by some "unsafe" usage?. In Go there are no threads (from a language perspective) and I do not understand what type of problem you expect from your code. – Volker Jun 09 '22 at 08:36
  • @Volker: Do you know about blocking and non-blocking calls in CPU bound task? – Arnold Zahrneinder Jun 09 '22 at 08:41
  • 2
    You need to explain what you think could be unsafe about using `time.Sleep`. What specific problem are you having? – JimB Jun 09 '22 at 11:18
  • @JimB: If a call is `blocking` the thread on which is the call takes place is blocked meaning that the corresponding thread is kept active but blocked. On the other hand, a non-blocking call suspends the thread and when it is finished, the corresponding thread resumes and this means that whatever scheduler that is behind it can run more threads in the meanwhile. This is what I meant by unsafe because I think it falls into the first scenario. – Arnold Zahrneinder Jun 10 '22 at 02:06
  • 2
    So you’re saying your definition of unsafe here equals “blocking”, but you said that you are not asking if `time.Sleep` is blocking — I’m not able to figure out where your misunderstanding lies. You do not have any access to threads in go, that is handled transparently by the runtime scheduler, as is `time.Sleep` itself. It would help if you had a concrete problem you are trying to solve here, because sleep does exactly what it’s document to do, nothing less and nothing more, which is _“[pause] the current goroutine for at least the duration d”_ – JimB Jun 10 '22 at 02:25
  • Sorry. you seem intent on forcing the concept of async/await functions in here, but it doesn’t apply to the go language. I’m not sure how else to answer this more precisely other than with the documentation for Sleep. Perhaps you are really trying to ask a question about a particular runtime implementation, but I can’t really fashion a question out of that either. – JimB Jun 10 '22 at 02:47
  • @Jim: can we have a short discussion in chat? – Arnold Zahrneinder Jun 10 '22 at 02:48
  • @JimB: I'd appreciate you if you help me with this question as well https://stackoverflow.com/questions/72568653/does-using-runtime-gosched-in-the-default-case-of-a-select-statement-make-an – Arnold Zahrneinder Jun 10 '22 at 03:00
  • Golang does not natively have async/await functions, but it has goroutines/channels. (Someone tried to create async/await functionality using goroutines and channels: https://hackernoon.com/asyncawait-in-golang-an-introductory-guide-ol1e34sg ) – qrsngky Jun 10 '22 at 04:18

2 Answers2

0

There's no async/await in go. To have a non-blocking sleep you have to wrap it in a goroutine. Then it can return its result to the main context using a channel message.

// create a channel to receive the return value of an asynchronous function
channel := make(chan bool)
// this is a goroutine which executes asynchronously
go func() {
    time.Sleep(5 * time.Second)
    // send a message to the channel
    channel <- true
}()
// setup a channel listener
select {
case val: <-channel:
    // Execute some code after a timeout, val contains the sent value
}
Pawel
  • 16,093
  • 5
  • 70
  • 73
  • I actually meant single threaded non-blocking operations. – Arnold Zahrneinder Jun 21 '23 at 02:46
  • go routines may create new threads or may choose context switching. That's not controllable. – Arnold Zahrneinder Jun 21 '23 at 02:46
  • @ArnoldZahrneinder go doesn't have explicit single-threaded concurrency. – Pawel Jun 21 '23 at 11:44
  • That somehow good and bad. Good because Rob Pike's goad was simplicity so he tried to offload such decisions, whether to go for concurrency or parallelism, from developers. But bad because if you are coming from a low level programing language and you really know what your are doing, then you lose control. I think Go is a great language but the Go Routine concept could be designed a little better. – Arnold Zahrneinder Jun 22 '23 at 05:51
  • @ArnoldZahrneinder if you're finding cases where it's a deal breaker it may be worth raising an issue in the language repo, or even building a POC in a fork https://github.com/golang/go – Pawel Jun 22 '23 at 11:47
-1

If you want a goroutine to wait for a specific amount of time, time.Sleep is the best, most correct way to do that.

Sleep pauses the current goroutine for at least the duration d

Hymns For Disco
  • 7,530
  • 2
  • 17
  • 33