Мы можем использовать только RWMutex без летучих? - PullRequest
0 голосов
/ 20 сентября 2019

В https://golang.org/ref/mem#tmp_10, эта программа не является безопасной, как показано ниже, нет гарантии, что вы напечатаете самую новую версию сообщения MSG

type T struct {
    msg string
}

var g *T

func setup() {
    t := new(T)
    t.msg = "hello, world"
    g = t
}

func main() {
    go setup()
    for g == nil {
    }
    print(g.msg)
}

В JAVA, нормально для volatile g, мы должны использовать rwmutexпродолжать печатать новейшие сообщения в golang, как показано ниже?


type T struct {
    msg    string
    rwlock sync.RWMutex
}

var g = &T{}

func setup() {
    g.rwlock.Lock()
    defer g.rwlock.Unlock()
    g.msg = "hello, world"
}

func main() {
    go setup()
    printMsg()
}

func printMsg() {
    g.rwlock.RLock()
    defer g.rwlock.RUnlock()
    print(g.msg)
}

Ответы [ 2 ]

1 голос
/ 20 сентября 2019

Вот еще несколько вариантов.

Ожидание при занятости.Эта программа завершает работу в текущей версии Go, но спецификация не гарантирует этого. Запустите его на детской площадке .

package main

import (
    "runtime"
    "sync/atomic"
    "unsafe"
)

type T struct {
    msg string
}

var g unsafe.Pointer

func setup() {
    t := new(T)
    t.msg = "hello, world"
    atomic.StorePointer(&g, unsafe.Pointer(t))
}

func main() {
    go setup()
    var t *T
    for {
        runtime.Gosched()

        t = (*T)(atomic.LoadPointer(&g))
        if t != nil {
            break
        }
    }
    print(t.msg)
}

Канал. Запустите его на детской площадке .

func setup(ch chan struct{}) {
    t := new(T)
    t.msg = "hello, world"
    g = t
    close(ch) // signal that the value is set
}

func main() {
    var ch = make(chan struct{})
    go setup(ch)
    <-ch // wait for the value to be set.
    print(g.msg)
}

WaitGroup . Запустите его на детской площадке .

var g *T

func setup(wg *sync.WaitGroup) {
    t := new(T)
    t.msg = "hello, world"
    g = t
    wg.Done()
}

func main() {
    var wg sync.WaitGroup
    wg.Add(1)
    go setup(&wg)
    wg.Wait()
    print(g.msg)
}
0 голосов
/ 20 сентября 2019

Я думаю, что лучше использовать канал.

type T struct {
    msg string
    doneC chan struct{}
}

func NewT() *T {
    return &T{
        doneC: make(chan struct{}, 1),
    }
}

func (t *T) setup() {
    t.msg = "hello, world"
    t.doneC <- struct{}{}
}

func main() {
    t := NewT()
    go t.setup()
    <- t.doneC // or use select to set a timeout
    fmt.Println(t.msg)
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...