dongpu5600 2018-07-09 16:15
浏览 99
已采纳

字符串和并发性的不变性

Should we synchronize on writing strings? Since string is immutable we will never get inconsistent state between write and read from the 2 different threads, right?

On other words, why we don't have atomic for string type?

  • 写回答

3条回答 默认 最新

  • duannao3819 2018-07-09 16:21
    关注

    string values are immutable, but variables are not. Variables are–what their name say–variable, their values can be changed.

    You don't need synchronization for accessing a string value, that can't change. If a string value is handed to you, that (the content of the string) will always remain the same (usage of package unsafe does not count).

    You need synchronization when you want to access a variable of string type from multiple goroutines concurrently, if at least one of the accesses is a write (a write that changes the value of the string variable). This is true for variables of any type in Go, the string type is not special in any way.

    What does this mean in practice?

    If you have a function that receives a string value "hello", you can be sure the string value will stay "hello" no matter what. Consequently if you don't change the argument yourself (e.g. you don't assign a new value to it), it will always hold the string value "hello".

    As a counter-example, if your function receives a slice value []byte{1, 2, 3}, you don't have the same guarantee, because slices are mutable. The caller also has the slice value (the slice header), else it couldn't pass it in the first place. And if the caller modifies the elements of the slice concurrently, since they share the same backing array, the slice that was handed to you will also see the changed data... with proper synchronization; because without synchronization this would be a data race (and hence undefined behavior).

    See this example:

    var sig = make(chan int)
    
    func main() {
        s := []byte{1, 2, 3}
        go func() {
            <-sig
            s[0] = 100
            sig <- 0
        }()
        sliceTest(s)
    }
    
    func sliceTest(s []byte) {
        fmt.Println("First  s =", s)
    
        sig <- 0 // send signal to modify now
        <-sig    // Wait for modification to complete
    
        fmt.Println("Second s =", s)
    }
    

    Output (try it on the Go Playground):

    First  s = [1 2 3]
    Second s = [100 2 3]
    

    Focus on sliceTest(): it receives a slice, and it prints it. Then waits a little (gives a "go" to a concurrent goroutine to modify it, and waits for this modification to complete), and prints it again, and it has changed, yet sliceTest() itself did not modify it.

    Now if sliceTest() would receive a string argument instead, this could not happen.

    See related / possible duplicate: Immutable string and pointer address

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥16 mybatis的代理对象无法通过@Autowired装填
  • ¥15 可见光定位matlab仿真
  • ¥15 arduino 四自由度机械臂
  • ¥15 wordpress 产品图片 GIF 没法显示
  • ¥15 求三国群英传pl国战时间的修改方法
  • ¥15 matlab代码代写,需写出详细代码,代价私
  • ¥15 ROS系统搭建请教(跨境电商用途)
  • ¥15 AIC3204的示例代码有吗,想用AIC3204测量血氧,找不到相关的代码。
  • ¥20 CST怎么把天线放在座椅环境中并仿真
  • ¥15 任务A:大数据平台搭建(容器环境)怎么做呢?