The goroutines of "the.go.programming.language.2015.11"

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed.

      • Process pictures in parallel and wait for the end of all picture processing
        • Limit concurrent Quantities
      • Multiplexing Select
        • Mutual exclusion Lock
      • Synconce
        • Workaround one using mutex lock
        • Solution two use a read-write lock
        • Workaround three Use Synconce

Process pictures in parallel and wait for the end of all picture processing

funcMAKETHUMBNAILS6 (Filenames <-Chan string)Int64{Sizes: = Make(Chan Int64)varWG Sync. Waitgroup//number of working Goroutines     forF: =RangeFilenames {WG. Add(1)//Worker        Go func(fstring) {deferWg. Done () thumb, err: = thumbnail. ImageFile (f)ifErr! =Nil{log. PRINTLN (ERR)return} info, _: = OS. Stat (thumb)//OK to ignore errorSizes <-Info. Size ()} (f)}//Closer    Go func() {WG. Wait ()Close(sizes)} ()varTotalInt64     forSize: =RangeSizes {Total + = size}returnTotal

This code is var wg sync.WaitGroup used to implement waiting for the end of all picture processing.
function makeThumbnails6 is executed to

forsize := range sizes {

When it is blocked until

    gofunc() {        wg.Wait()        close(sizes)    }()

Executed to close(sizes) . The Goroutine first blocks on wg.Wait() until all of the picture processing is finished and the image processing is finished at the end of the call wg.Done() .

Limit concurrent Quantities

The simplest is achieved through a channel with a cache
As below, the call tokens <- struct{}{} gets a quota before execution, and the release quota is called after execution ends <-tokens .

//tokens is a counting semaphore used to< /span>//enforce a limit of concurrent requests.  var  tokens = make  ( chan  struct  {}, ) func  crawl (url string ) []string  {fmt. Println (URL) tokens <-struct  {} {} //acquire a token< /span> list, err: = links.  Extract (URL) <-tokens //release the token  if  Err! = nil  {log. Print (Err)} return  list}  

Multiplexing Select

time.TickCreate a channel that writes data to the channel every once in a while.

func main() {    fmt.Println("Commencing countdown.")    ticktime.Tick(1time.Second)    for100; countdown-- {        fmt.Println(countdown)        <-tick    }    launch()}

Use when waiting for multiple channelsselect

.........}

Select blocks until a channel is available and, if more than one is available, randomly selects one.

time.AfterGenerates a channel after a specified time and produces a goroutine that writes a value to the channel.

func main() {    // ...create abort channel...    fmt.Println("Commencing countdown. Press return to abort.")    select {    case <-time.After(10 * time.Second):    // Do nothing.    case <-abort:        fmt.Println("Launch aborted!")        return    }    launch()}

Timers are commonly used in the following ways:

ticker := time.NewTicker(1from the ticker's channelticker.Stop() // cause the ticker's goroutine to terminate

Non-blocking mode

select {    case <-abort:        fmt.Printf("Launch aborted!\n")        return    default:    // do nothing}

The 0 value of the channel is nil. Read and write on nil channels will always block. Case in Select

Mutual exclusion Lock

var (    mu    // guards balance    int)funcint) {    mu.Lock()    balance = balance + amount    mu.Unlock()}funcint {    mu.Lock()    defer mu.Unlock()    return balance}

This article also gives an example, if the account balance is insufficient, it will be back to the operation, Deposit(-amount) indicating the purchase operation, to determine the Balance() balance is insufficient:

// NOTE: not atomic!funcintbool {    Deposit(-amount)    if Balance() < 0 {        Deposit(amount)        returnfalse// insufficient funds    }    returntrue}

The problem with this code is that if a has 100 yuan, want to buy 300 of the car, Deposit(-amount) resulting Balance() in negative, then if Deposit(amount) before a to buy less than 100 yuan of daily necessities can not buy, because at this time balance () is still negative, has not recovered.
So to buy and restore as an atomic operation.

funcWithdraw (Amountint)BOOL{mu. Lock ()deferMu. Unlock () deposit (-amount)ifBalance <0{Deposit (amount)return false //Insufficient funds}return true}funcDeposit (Amountint) {mu. Lock ()deferMu. Unlock () Deposit (amount)}funcBalance ()int{mu. Lock ()deferMu. Unlock ()returnBalance//This function requires that the lock is held.funcDeposit (Amountint) {balance + = amount}

Sync. Once

First, let's look at the following code

varIconsMap[string]image. ImagefuncLoadicons () {icons =Map[string]image. image{"Spades.png": LoadIcon ("Spades.png"),"Hearts.png": LoadIcon ("Hearts.png"),"Diamonds.png": LoadIcon ("Diamonds.png"),"Clubs.png": LoadIcon ("Clubs.png"),    }}//Note:not concurrency-safe!funcIcon (namestring) image. Image {ificons = =Nil{loadicons ()//One-time initialization}returnIcons[name]}

Where Icon the function is not concurrency-safe , if there are two Goroutines A and b,a first executed to if icons == nil then switch to b,b at this time the judgment if icons == nil is still true, so loadIcons it executes two times.

Workaround one, use mutual exclusion locks:

var// guards icons// Concurrency-safe.funcstring) image.Image {    mu.Lock()    defer mu.Unlock()    ifnil {        loadIcons()    }    return icons[name]}

However, the problem is that after icons is initialized, subsequent read operations cannot be performed in parallel.

Solution two use a read-write lock

var  mu sync. Rwmutex //guards icons  var  icons map  [string ]image. Image//concurrency-safe.  func  Icon (name string ) image. Image {mu. Rlock () if  icons! = nil  {icon: = Icons[nam E] Mu. Runlock () return  icon} mu. Runlock () //acquire an exclusive lock  Mu. Lock () if  icons = nil  {//note:must recheck for nil  loadicons ()} icon: = Icons[name] mu. Unlock () return  icon} 

The problem is that it costs too much.

Workaround three use sync. Once

var loadIconsOnce sync.Oncevarmap[string]image.Image// Concurrency-safe.funcstring) image.Image {    loadIconsOnce.Do(loadIcons)    return icons[name]}
Related Article

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.