第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問題,去搜搜看,總會(huì)有你想問的

同時(shí),如何管理值/狀態(tài)并避免競(jìng)爭(zhēng)條件

同時(shí),如何管理值/狀態(tài)并避免競(jìng)爭(zhēng)條件

Go
慕標(biāo)琳琳 2022-03-03 15:57:47
如何根據(jù)進(jìn)程啟動(dòng)后發(fā)生的事件/條件正確設(shè)置/修改值,同時(shí)在不創(chuàng)建競(jìng)爭(zhēng)條件的情況下處理Goroutine 。例如,以下“有效(錯(cuò)誤)”,輸出為:ping, foo=trueping, foo=falseping, foo=trueping, foo=trueping, foo=truehttps://play.golang.org/p/Y3FafF-nBcpackage mainimport "fmt"type test struct {    ch  chan string    foo bool}func (t *test) run() {    for {        select {        case v := <-t.ch:            fmt.Printf("%+v, foo=%+v\n", v, t.foo)            t.foo = false        default:        }    }}func (t *test) Ping() {    t.ch <- "ping"}func New() *test {    t := &test{        ch: make(chan string),    }    go t.run()    return t}func main() {    t := New()    for i := 0; i <= 10; i++ {        if t.foo {            t.Ping()        }        if i%3 == 0 {            t.foo = true        }    }}但是,如果使用-race選項(xiàng)編譯或運(yùn)行,我會(huì)得到以下輸出:$ go run -race main.goping, foo=true==================WARNING: DATA RACEWrite at 0x00c4200761b8 by goroutine 6:  main.(*test).run()      /main.go:16 +0x1fbPrevious read at 0x00c4200761b8 by main goroutine:  main.main()      /main.go:37 +0x5eGoroutine 6 (running) created at:  main.New()      /main.go:30 +0xd0  main.main()      /main.go:35 +0x33==================ping, foo=falseping, foo=trueping, foo=trueping, foo=trueFound 1 data race(s)exit status 66因此,我想知道我可以使用什么并發(fā)模式來更改foogorutine 外部和 gorutine 內(nèi)部的值,而不會(huì)產(chǎn)生競(jìng)爭(zhēng)條件。
查看完整描述

2 回答

?
子衿沉夜

TA貢獻(xiàn)1828條經(jīng)驗(yàn) 獲得超3個(gè)贊

你有一些選擇:

  • 使用atomic.Value:樣品 (1)

  • 使用sync.RWMutex:樣品 (3)

  • 使用sync/atomic:樣品 (6)

  • 僅使用通道和 goroutine:示例 (7)

另請(qǐng)參閱: 使用 sync.Mutex 還是通道?


1-您可以使用atomic.Value

值提供了一致類型值的原子加載和存儲(chǔ)。值可以作為其他數(shù)據(jù)結(jié)構(gòu)的一部分創(chuàng)建。Value 的零值從 Load 返回 nil。調(diào)用 Store 后,不得復(fù)制 Value。

首次使用后不得復(fù)制值。

像這個(gè)工作樣本:

// to test the panic use go build -race

package main


import (

    "fmt"

    "sync/atomic"

)


type test struct {

    ch chan string

    atomic.Value

}


func (t *test) run() {

    for {

        select {

        case v := <-t.ch:

            fmt.Printf("%+v, foo=%+v\n", v, t.Load())

            t.Store(false)

        default:

        }

    }

}


func (self *test) Ping() {

    self.ch <- "ping"

}


func New() *test {

    t := &test{

        ch: make(chan string),

    }

    t.Store(false)

    go t.run()

    return t

}


func main() {

    t := New()

    for i := 0; i <= 10; i++ {

        if x, _ := t.Load().(bool); x {

            t.Ping()

        }

        //  time.Sleep(time.Second)

        if i%3 == 0 {

            t.Store(true)

        }

    }

}

輸出go build -race:


ping, foo=true

ping, foo=false

ping, foo=false

ping, foo=false

ping, foo=false

2- 一點(diǎn)改進(jìn)func (t *test) run():


func (t *test) run() {

    for v := range t.ch {

        fmt.Printf("%+v, foo=%+v\n", v, t.Load())

        t.Store(false)

    }

}

3-您可以使用sync.RWMutexand sync.WaitGroup,就像這個(gè)工作示例一樣:


// to test the panic use go build -race

package main


import (

    "fmt"

    "sync"

)


type test struct {

    ch  chan string

    foo bool

    sync.RWMutex

    sync.WaitGroup

}


func (t *test) run() {

    for v := range t.ch {

        t.Lock()

        r := t.foo

        t.foo = false

        t.Unlock()

        fmt.Printf("%+v, foo=%+v\n", v, r)


    }

    t.Done()

}


func (self *test) Ping() {

    self.ch <- "ping"

}


func New() *test {

    t := &test{ch: make(chan string)}

    t.Add(1)

    go t.run()

    return t

}


func main() {

    t := New()

    for i := 0; i <= 10; i++ {

        t.RLock()

        r := t.foo

        t.RUnlock()

        if r {

            t.Ping()

        }

        //  time.Sleep(time.Second)

        if i%3 == 0 {

            t.Lock()

            t.foo = true

            t.Unlock()

        }

    }

    close(t.ch)

    t.Wait()

}

輸出go build -race:


ping, foo=true

ping, foo=true

ping, foo=false

ping, foo=true

ping, foo=false

ping, foo=true

4-所以讓我們按照這種方法https://talks.golang.org/2013/bestpractices.slide#29:

原始代碼:


package main


import (

    "fmt"

    "time"

)


type Server struct{ quit chan bool }


func NewServer() *Server {

    s := &Server{make(chan bool)}

    go s.run()

    return s

}


func (s *Server) run() {

    for {

        select {

        case <-s.quit:

            fmt.Println("finishing task")

            time.Sleep(time.Second)

            fmt.Println("task done")

            s.quit <- true

            return

        case <-time.After(time.Second):

            fmt.Println("running task")

        }

    }

}

func (s *Server) Stop() {

    fmt.Println("server stopping")

    s.quit <- true

    <-s.quit

    fmt.Println("server stopped")

}


func main() {

    s := NewServer()

    time.Sleep(2 * time.Second)

    s.Stop()

}

5-讓我們簡化它:


package main


import (

    "fmt"

    "time"

)


var quit = make(chan bool)


func main() {

    go run()

    time.Sleep(2 * time.Second)

    fmt.Println("server stopping")


    quit <- true // signal to quit


    <-quit // wait for quit signal


    fmt.Println("server stopped")

}


func run() {

    for {

        select {

        case <-quit:

            fmt.Println("finishing task")

            time.Sleep(time.Second)

            fmt.Println("task done")

            quit <- true

            return

        case <-time.After(time.Second):

            fmt.Println("running task")

        }

    }

}

輸出:


running task

running task

server stopping

finishing task

task done

server stopped

6-您的樣本的簡化版本:


// to test the panic use go build -race

package main


import "fmt"

import "sync/atomic"


var ch = make(chan string)

var state int32


func main() {

    go run()

    for i := 0; i <= 10; i++ {

        if atomic.LoadInt32(&state) == 1 {

            ch <- "ping"

        }

        if i%3 == 0 {

            atomic.StoreInt32(&state, 1)

        }

    }

}


func run() {

    for v := range ch {

        fmt.Printf("%+v, state=%+v\n", v, atomic.LoadInt32(&state))

        atomic.StoreInt32(&state, 0)

    }

}

輸出:


ping, state=1

ping, state=0

ping, state=1

ping, state=0

ping, state=1

ping, state=0

7- 帶通道但不使用Lock()(The Go Playground)的工作樣本:


// to test the panic use go build -race

package main


import "fmt"


func main() {

    go run()

    for i := 0; i <= 10; i++ {

        signal <- struct{}{}

        if <-read {

            ping <- "ping"

        }

        if i%3 == 0 {

            write <- true

        }

    }

}


func run() {

    foo := false

    for {

        select {

        case <-signal:

            fmt.Println("signal", foo)

            read <- foo

        case foo = <-write:

            fmt.Println("write", foo)

        case v := <-ping:

            fmt.Println(v, foo)

            foo = false

        }

    }

}


var (

    ping   = make(chan string)

    signal = make(chan struct{})

    read   = make(chan bool)

    write  = make(chan bool)

)

輸出:


signal false

write true

signal true

ping true

signal false

signal false

write true

signal true

ping true

signal false

signal false

write true

signal true

ping true

signal false

signal false

write true

signal true

ping true


查看完整回答
反對(duì) 回復(fù) 2022-03-03
?
幕布斯6054654

TA貢獻(xiàn)1876條經(jīng)驗(yàn) 獲得超7個(gè)贊

使用互斥鎖

package main


import (

    "sync"

    "time"

    "fmt"

)


var myvar int

var mut sync.Mutex


func main() {

    for {

        go other()

        go printer()

        time.Sleep(time.Duration(1) * time.Second)

    }

}


func other() {

    mut.Lock()

    myvar = myvar +1

    mut.Unlock()

}


func printer() {

    mut.Lock()

    fmt.Println(myvar)

    mut.Unlock()

}

運(yùn)行(使用互斥鎖)

$ go build -race t1.go 

$ ./t1 

1

2

3

4

5

6

7

7

9

10

運(yùn)行(沒有互斥體)

$ go build t2.go 

$ go build -race t2.go 

$ ./t2 

==================

WARNING: DATA RACE

Read at 0x000000580ce8 by goroutine 7:

  runtime.convT2E()

      /usr/local/go/src/runtime/iface.go:155 +0x0

  main.printer()

      /.../.../.../GOPATH/t2.go:23 +0x65


Previous write at 0x000000580ce8 by goroutine 6:

  main.other()

      /.../.../.../GOPATH/t2.go:19 +0x3d


Goroutine 7 (running) created at:

  main.main()

      /.../.../.../GOPATH/t2.go:13 +0x5a


Goroutine 6 (finished) created at:

  main.main()

      /.../.../.../GOPATH/t2.go:12 +0x42

==================

1

2


查看完整回答
反對(duì) 回復(fù) 2022-03-03
  • 2 回答
  • 0 關(guān)注
  • 168 瀏覽

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)