Some of timer pit golang

Article code portions dive-to-gosync-workshop based code

After the NewTimer Golang method call, the timer will generate a minimum stack placed, a background goroutine scans the stack, the timer and the time of the callback Channel (following code c: = make (chan Time, 1)) is written

// NewTimer creates a new Timer that will send
// the current time on its channel after at least duration d.
func NewTimer(d Duration) *Timer {
	c := make(chan Time, 1)
	t := &Timer{
		C: c,
		r: runtimeTimer{
			when: when(d),
			f:    sendTime,
			arg:  c,
		},
	}
	startTimer(&t.r)
	return t
}

  The Stop method of golang the timer, the timer is only responsible for removing from the crowd, is not responsible for close above channel (why not close channel? Just to see the current time-out, the underlying code to handle simple not crash. In fact, the official is golang done correctly handle the channel timeout), so buy some pit.

    The following code shows the pits and processing method wherein wrongResetAfterFired (..) described channel after a timeout is written, if not active correctly received , the Timer reset will lead to still get the last channel from the channel data.

   The wrongStopMore (...) shows that if channel is not written, and do not go directly to the waiting will lead to deadlock

 

 

 

main Package Penalty for 

Import ( 
	"fmt" 
	"log" 
	"Time" 
) 

// [JZ] on timer is a more important point is that after newtimer, timer will be placed in the smallest heap, then there is a goroutine to scan, due to call back and channel write 
// stop is only responsible for the timer is removed from the reactor, is not responsible for channel use Close 
FUNC main () { 
	log.Println ( "✔︎ resetBeforeFired") 
	resetBeforeFired () 
	fmt.Println () 

	log.Println ( "✘ wrongResetAfterFired") 
	wrongResetAfterFired () 
	fmt.Println () 

	log.Println ( "✔︎ correctResetAfterFired") 
	correctResetAfterFired () 
	fmt.Println () 

	log.Println ( "STOP ✔︎ n-Times") 
	stopMore () 
	fmt.Println () 

	log.Println ( "✘ stop n times but with drain ")
	wrongStopMore()
	fmt.Println () 
	t: = <-timer.C

	log.Println ( "TOO MANY ✘ Receiving") 
	wrongReceiveMore () 
} 

FUNC resetBeforeFired () { 
	Timer: time.NewTimer = (. 5 * time.Second) 
	B: = Timer.stop () 
	log.Printf ( "STOP:% T ", B) 
	Timer.reset (* time.Second. 1) 
	T: = <-timer.C 
	log.Printf ("% S AT fired ", t.String ()) 
} 

FUNC wrongResetAfterFired () { 
	Timer: = Time. NewTimer (. 5 * time.Millisecond) 
	time.sleep (time.Second) // SLEEP lS ensure the above timer expires, channel are written 

	B: = Timer.stop () 
	log.Printf ( "STOP:% T", B) 
	TT: Timer.reset = (10 * time.Second) 
	fmt.Println (TT) 
	// get at this time is the first timeout timer (5 ms the) value of the channel 
	log.Printf ( "fired at % s ", t.String())
}

correctResetAfterFired FUNC () { 
	Timer: time.NewTimer = (. 5 * time.Millisecond) 
	time.sleep (time.Second) 

	B: = Timer.stop () 
	log.Printf ( "STOP:% T", B) 
	// if stop when the discovery time expires in the write channel should read, so that before the readout channel later reset the value in the 
	IF {B! 
		T: = <-timer.C 
		fmt.Println (t.String ()) 
	} 
	log.Printf ( "RESET") 
	Timer.reset (10 * time.Second) 
	T: = <-timer.C 
	log.Printf ( "% S AT fired", t.String ()) 
} 

FUNC wrongReceiveMore () { 
	Timer: time.NewTimer = (. 5 * time.Millisecond) 
	T: = <-timer.C 
FUNC stopMore () { 
	log.Printf ( "fired AT% s ", t.String())

	t = <-timer.C
	log.Printf ( "AT% Again the receive S", t.String ()) 
} 

	Timer: time.NewTimer = (. 5 * time.Millisecond) 
	B: = Timer.stop () 
	log.Printf ( "STOP:% T" , B) 
	time.sleep (time.Second) 
	B = Timer.stop () 
	log.Printf ( "More STOP:% T", B) 
} 

/ * 
	after newtimer, timer will be placed in the minimum heap, and then to a goroutine scan, due callbacks and write channel 
 	stop timer is only responsible removed from the stack, is not responsible for channel Close 
* / 
FUNC wrongStopMore () { 
	timer: time.NewTimer = (. 5 * time.Millisecond) 
	B: = Timer.stop () 
	log.Printf ( "STOP:% T", B) 
	time.sleep (time.Second) 
	B = Timer.stop () 
	! B {// IF can be considered resolved:! if b && len (timer.C )> 0 
		// The reason why the problem is that, for the first time Stop calling, It occurred before the timer expires, the timer has been removed from the stack at this time, but does not have a timeout timer, so no need to send Channel 
		// at this point you will not have to wait for the results of timer.C
		// For example, you first timer.Stop before sleep 1s, let the timer timeout, channel will be written, then there is no problem waiting timer .C 
		<-timer.C 
	} 
	the time.sleep (1 * Time. SECOND) 
	log.Printf ( "More STOP:% T", B) 
}

 

    

Guess you like

Origin www.cnblogs.com/jiangz222/p/11622495.html