Golang Competitive Status

Source: Internet
Author: User

Look at the code:

Package Mainimport ("FMT" "Runtime" "Sync") var (counter INTWG Sync. Waitgroup) Func main () {WG. ADD (2) Go inccounter (1) Go Inccounter (2) WG. Wait () fmt. Println ("Final Counter:", Counter)}func inccounter (id int) {defer WG. Done () for count: = 0; Count < 2; count++ {value: = Idruntime. Gosched () Value++counter = value}}

Goroutine executes a copy value and then writes the copy value to counter, so when you switch Goroutine, the value in Goroutine overrides counter. Where the gosched function is used in the runtime package to exit Goroutine from the current thread, giving other goroutine the opportunity to run. This code execution down in theory should be the existence of competitive state, for counter this variable, in two goroutine switch, altogether added 4 times, but because each time after switching into the queue is not the true value, but a copy, the result output should be 2.

The truth seems to be like this ... Looks like a little bit of a problem ...

Check the competition status, then put this gosched function comment, and then re-detect the competition status, successively compiled to achieve the following:

Why is this happening? Final Counter:3

==================warning:data racewrite at 0x0000005b73c0 by Goroutine 6: Main.inccounter ()/home/qmq/gopath/src/github.com/goinaction/code/test.go:49 +0x74previous write at 0x0000005b73c0 b Y goroutine 7:main.inccounter ()/home/qmq/gopath/src/github.com/goinaction/code/test.go:49 +0x74Goroutine 6 (runnin g) created At:main.main ()/home/qmq/gopath/src/github.com/goinaction/code/test.go:25 +0x68goroutine 7 (running) CRE Ated at:main.main ()/home/qmq/gopath/src/github.com/goinaction/code/test.go:26 +0x89==================final Counte R:2found 1 Data race (s) 
==================warning:data Racewrite at 0x0000005b73c0 by Goroutine 7:  main.inccounter ()      /home/qmq/ gopath/src/github.com/goinaction/code/test.go:49 +0x74previous write at 0x0000005b73c0 by Goroutine 6:  Main.inccounter ()      /home/qmq/gopath/src/github.com/goinaction/code/test.go:49 +0x74goroutine 7 (running) Created at:  main.main ()      /home/qmq/gopath/src/github.com/goinaction/code/test.go:26 +0x89goroutine 6 ( Finished) created at:  main.main ()      /home/qmq/gopath/src/github.com/goinaction/code/test.go:25 +0x68======= ===========final counter:3found 1 Data race (s) ================

The output small probability is 3, it is possible that Goroutine did not exit, so the value in the new Goroutine has been added to the last Goroutine copy value. The ability to work with multiple goroutine on a shared resource requires locking it, using a simple atomic, and using Go's featured channel.

1. Mutual exclusion Lock

Package Mainimport ("FMT" "Runtime" "Sync") var (counter INTWG Sync. Waitgroup        //Mutex    mutex sync. Mutex) Func main () {WG. ADD (2) Go inccounter (1) Go Inccounter (2) WG. Wait () fmt. Printf ("Final Counter:%d\n", Counter)}func inccounter (id int) {defer WG. Done () for count: = 0; Count < 2; The count++ {               //Mutex locks the critical code block, allowing only one goroutine to access the mutex at the same time. Lock () {///habitually add braces clearer//Capture the value of counter.value: = counter//Yield The thread and be placed back in Queue.runt Ime. Gosched ()//Increment Our local value of counter.value++//Store, the value back into Counter.counter = Value}mutex. Unlock ()//Unlock}}

2.atomic Pack

Package Mainimport ("FMT" "Sync" "sync/atomic" "Time") var (shutdown INT64WG Sync. Waitgroup) Func main () {WG. ADD (2) Go doWork ("A") Go doWork ("B")        //Set time for goroutine execution. Sleep (1 * time. Second) fmt. Println ("Shutdown Now")        //Safety signs determine whether Goroutine work atomic can be stopped. StoreInt64 (&shutdown, 1) WG. Wait ()}func doWork (name string) {defer WG. Done () for {fmt. Printf ("Doing%s work\n", name) time. Sleep (Time.millisecond) if atomic. LoadInt64 (&shutdown) = = 1 {fmt. Printf ("Shutting%s down\n", name) Break}}}

3. Channel

Package Mainimport ("FMT" "Math/rand" "Sync" "Time") var wg sync. Waitgroupfunc init () {rand. Seed (time. Now (). Unixnano ())}func main () {court: = make (chan int) WG. ADD (2) Go player ("Ding", court) Go player ("Sha", court) court <-1WG. Wait ()}func player (name string, Court Chan int) {defer WG. Done () for {ball, OK: = <-courtif!ok {fmt. Printf ("Player%s won\n", name) Return}n: = Rand. INTN (+) If n%13 = = 0 {fmt. Printf ("Player%s missed\n", name) Close (court) return}fmt. Printf ("Player%s hit%d\n", Name, Ball) Ball++court <-Ball}}

  

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.