在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 問答/GO  iOS/ golang中鎖的值類型和引用類型區(qū)別

golang中鎖的值類型和引用類型區(qū)別

在對象中引入Mutex來保證原子性,但是當(dāng)對象是值引用的時候,發(fā)現(xiàn)索沒有效果。它內(nèi)部的實現(xiàn)邏輯到底是怎么樣的?

代碼如下:

package main

import (
    "fmt"
    "sync"
)

//這里聲明了對象
type people struct {
    sync.Mutex
}

//它的值類型的方法
func (p people) test(str string) {
    p.Lock();
    defer p.Unlock();

    for i := 0; i < 5; {
        fmt.Println(str, i)
        i++
    }
}

func main() {
    var user people
    var wg sync.WaitGroup

    wg.Add(2)
    go func() {
        defer wg.Done()
        user.test("go1")
    }()

    go func() {
        defer wg.Done()
        user.test("go2")
    }()

    wg.Wait()
}

這樣執(zhí)行的話,看不出效果來,然后加上這樣一行代碼:

func (p people) test(str string) {
    p.Lock();
    defer p.Unlock();

    for i := 0; i < 5; {
        fmt.Println(str, i)
        
        //加的代碼在這里!這里!
        time.Sleep(time.Second)
        i++
    }
}

發(fā)現(xiàn)執(zhí)行的結(jié)果如下:

go2 0
go1 0
go2 1
go1 1
go1 2
go2 2
go2 3
go1 3
go1 4
go2 4

疑惑點:在整個邏輯過程中,只有一個變量user,沒有發(fā)生值拷貝的過程,怎么好端端的鎖就不生效了呢

回答
編輯回答
痞性

寫代碼嘗試了一下:確實如閣下說的一樣。所以我總結(jié)一下:

  1. 針對值調(diào)用的方法,在方法體內(nèi)部會復(fù)制對象的一份副本,該副本無法保存,在方法調(diào)用結(jié)束后被釋放。所以,要想讓方法體內(nèi)的對象保存新的修改,需要使用引用調(diào)用。
  2. 下面代碼中,只對象聲明的user,不能理解為對象,而應(yīng)該看做是一種調(diào)用的形式。當(dāng)然只是針對值聲明的類型函數(shù)。
func (p people) getAge() int  {
    return p.age
}

func (p people) setAge(newAge int)  {
    p.age = newAge
    fmt.Println("copy a object. age ", p.age)
}

func main() {
    var user people
    user.setAge(1)
    fmt.Println(user.getAge())
}
2018年9月9日 09:40
編輯回答
懶洋洋

首先mutex不能被拷貝,一旦mutex被拷貝,加鎖及解鎖就作用在不同的mutex對象上,自然就失去了效果.

另外對于方法的接收對象,接收者是值和指針是有本質(zhì)區(qū)別的:
1.當(dāng)接收者是指針時進行函數(shù)調(diào)用時傳遞的是該對象的指針.
2.當(dāng)接收者是值時進行函數(shù)調(diào)用傳遞的就是值拷貝.
這里可以通過在函數(shù)調(diào)用中對對象的值進行更改進行驗證.

因此,people對象進行函數(shù)調(diào)用時,people已經(jīng)拷貝了新值,生成了新的mutex,所以鎖就失效了.這里將test方法接收者改成*people即可.

2017年12月20日 04:12
編輯回答
維她命
func (p *people) test(str string) {
    // balabala
}
2018年6月12日 13:46