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

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

一段時間后停止 goroutine

一段時間后停止 goroutine

Go
江戶川亂折騰 2023-08-14 17:04:33
像這樣在一段時間后停止 goroutine 并發(fā)安全嗎?(注意:由于另一個 goroutine 發(fā)生變化而導致數(shù)據(jù)競爭):okpackage mainimport (? ? "fmt"? ? "time")func main() {? ? var ok byte? ? time.AfterFunc(1000*time.Millisecond, func() {? ? ? ? ok = 1? ? })? ? var i uint64? ? for ok == 0 {? ? ? ? i++ // CPU intensive task? ? }? ? fmt.Println(i) // 2_776_813_033}終端:go run -race .==================WARNING: DATA RACEWrite at 0x00c000132010 by goroutine 8:? main.main.func1()? ? ? ./main.go:11 +0x46Previous read at 0x00c000132010 by main goroutine:? main.main()? ? ? ./main.go:15 +0xf4Goroutine 8 (running) created at:? time.goFunc()? ? ? go/src/time/sleep.go:180 +0x51==================80849692Found 1 data race(s)代碼(無數(shù)據(jù)競爭):package mainimport (? ? "fmt"? ? "sync/atomic"? ? "time")func main() {? ? var ok int32? ? time.AfterFunc(1000*time.Millisecond, func() {? ? ? ? atomic.StoreInt32(&ok, 1)? ? })? ? var i uint64? ? for atomic.LoadInt32(&ok) == 0 {? ? ? ? i++ // CPU intensive task? ? }? ? fmt.Println(i) // 2_835_935_488}終端:go run -race .31934042
查看完整描述

2 回答

?
慕勒3428872

TA貢獻1848條經(jīng)驗 獲得超6個贊

即使被另一個 goroutineok設(shè)置為busy-wait for 循環(huán),也不能保證它會終止。false在設(shè)置和讀取 的過程中沒有顯式同步ok,因此不能保證主 Goroutine 能夠看到對其所做的更改。換句話說,沒有辦法在兩個 goroutine 之間建立發(fā)生之前的關(guān)系。

https://golang.org/ref/mem

代碼的第二個版本是安全的,盡管 Go 內(nèi)存模型中沒有針對 進行說明ok,但它并不安全,因為如此緊密的循環(huán)可能不允許其他 goroutine 執(zhí)行。原子讀/寫具有發(fā)生之前關(guān)系所需的內(nèi)存屏障。您應(yīng)該使用同步原語之一(互斥體、通道)來保證這一點。


查看完整回答
反對 回復 2023-08-14
?
繁花不似錦

TA貢獻1851條經(jīng)驗 獲得超4個贊

第二個代碼適用于 Go 1.14+:


去1.14


Goroutines 現(xiàn)在是異步可搶占的。因此,沒有函數(shù)調(diào)用的循環(huán)不再可能導致調(diào)度程序死鎖或顯著延遲垃圾收集。除了 windows/arm、darwin/arm、js/wasm 和 plan9/* 之外,所有平臺都支持此功能。


一段時間后停止 goroutine

BenchmarkAfterFunc-8            1000000000 0.4468 ns/op  0 B/op  0 allocs/op

BenchmarkDoneChannel-8          121966824   9.855 ns/op  0 B/op  0 allocs/op

BenchmarkTimeSince-8            89790115    12.95 ns/op  0 B/op  0 allocs/op

BenchmarkContextErr-8           58508900    19.78 ns/op  0 B/op  0 allocs/op

BenchmarkAfterFuncMutex-8       58323207    20.00 ns/op  0 B/op  0 allocs/op

BenchmarkContext-8              48947625    27.43 ns/op  0 B/op  0 allocs/op

測試:


package main


import (

    "context"

    "sync"

    "sync/atomic"

    "testing"

    "time"

)


const d = 200 * time.Millisecond //  To stop a task after a period of time


func BenchmarkTimeSince(b *testing.B) {

    t0 := time.Now()

    var count = 0

    for i := 0; i < b.N; i++ {

        if time.Since(t0) < d {

            count++

        }

    }

    _ = count

}


func BenchmarkContext(b *testing.B) {

    var ctx, cancel = context.WithTimeout(context.Background(), d)

    defer cancel()

    var count = 0

    for i := 0; i < b.N; i++ {

        select {

        case <-ctx.Done():

            // break

        default:

            count++

        }

    }

    _ = count

}

func BenchmarkContextErr(b *testing.B) {

    var ctx, cancel = context.WithTimeout(context.Background(), d)

    defer cancel()

    var count = 0

    for i := 0; i < b.N; i++ {

        if ctx.Err() == nil {

            count++

        }

    }

    _ = count

}


func BenchmarkAfterFunc(b *testing.B) {

    var done uint32

    time.AfterFunc(d, func() { atomic.StoreUint32(&done, 1) })

    var count = 0

    for i := 0; i < b.N; i++ {

        if atomic.LoadUint32(&done) == 0 {

            count++

        }

    }

    _ = count

}


func BenchmarkDoneChannel(b *testing.B) {

    var done = make(chan struct{})

    time.AfterFunc(d, func() { close(done) })

    var count = 0

    for i := 0; i < b.N; i++ {

        select {

        case <-done:

            // break

        default:

            count++

        }

    }

    _ = count

}


type foo struct {

    sync.Mutex

    state bool

}


func (p *foo) end() {

    p.Lock()

    p.state = true

    p.Unlock()

}

func (p *foo) isDone() bool {

    var b bool

    p.Lock()

    b = p.state

    p.Unlock()

    return b

}

func BenchmarkAfterFuncMutex(b *testing.B) {

    var it = foo{}

    time.AfterFunc(d, func() { it.end() })

    var count = 0

    for i := 0; i < b.N; i++ {

        if it.isDone() {

            count++

        }

    }

    _ = count

}


https://medium.com/a-journey-with-go/go-asynchronous-preemption-b5194227371c


搶占是調(diào)度程序的重要組成部分,它可以在 goroutine 之間分配運行時間。事實上,如果沒有搶占,一個長時間運行的 goroutine 會占用 CPU,從而阻止其他 goroutine 被調(diào)度。1.14版本引入了異步搶占的新技術(shù),為調(diào)度程序提供了更多的權(quán)力和控制權(quán)。


查看完整回答
反對 回復 2023-08-14
  • 2 回答
  • 0 關(guān)注
  • 171 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學習伙伴

公眾號

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