简体   繁体   中英

[Go]Is map[string] chan thread safe?

thanks for helping me in this question.

To my acknowledge, in golang map is non-thread-safe but chan is thread-safe.But what if i use chan as map 's value? Will this map become thread safe?

I write a simple test(don't know if this is the currect way to prove) as shown below, and run it for about 30 times without concurrent map read/write error .Does this means thread-safe chan makes the non-thread-safe map thread-safe?

Whether the map become thread safe, can anyone explain this a little bit deeper for me?Thanks!

import (
    "fmt"
    "math/rand"
    "time"
)

func main() {
    rand.Seed(time.Now().Unix())
    te := &testS{
        name: "test",
        val: map[string]chan int{
            "a": make(chan int, 10000000),
        },
    }

    for i := 0; i < 50000; i++ {
        te.val["a"] <- i
    }

    for i := 0; i < 30000; i++ {
        go write(te)
        go read(te)
    }
    for {
        fmt.Println("Waiting")
        time.Sleep(time.Second)
    }
}

func read(t *testS) {
    time.Sleep(time.Duration(rand.Intn(3)) * time.Second)
    <-t.val["a"]
    fmt.Println("read")
}

func write(t *testS) {
    time.Sleep(time.Duration(rand.Intn(3)) * time.Second)
    t.val["a"] <- 1
    fmt.Println("write")
}

type testS struct {
    name string
    val  map[string]chan int
}

I think i got this question sovled. As @mkopriva says, this example actually never write to the map . But this example can also helps me understanding this question:

Read/Writing to the chan acutually doesn't affect the map , you can think the map is storaging the channel's address, only if you delete or add something to the map will you write to it. Reading/Writing to the `chann`` doesn't affect its address, so won't "write" to the map.

In one word: Reading/Writing the chan is not related to reading/writing the map

Also i have another test for prove it:

test := map[string]chan int{
        "a": make(chan int, 1000),
    }

    for i := 0; i < 200; i++ {
        test["a"] <- i
    }

    go func() {
        for {
            fmt.Printf("get from chan: %d\n", <-test["a"])
            time.Sleep(time.Second)
        }
    }()

    time.Sleep(5 * time.Second)
    newChan := make(chan int, 1000)
    for i := 200; i > 0; i-- {
        newChan <- i
    }
    test["a"] = newChan
    for {
        fmt.Println("waiting")
        time.Sleep(time.Second)
    }

You will see that after changing test["a"] to newChan , the output will start print the element in newChan

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM