代码之家  ›  专栏  ›  技术社区  ›  drainzerrr

Go锁定结构的一部分

  •  0
  • drainzerrr  · 技术社区  · 6 年前

    我是新来的。我特别尝试使用锁向数组中并行添加值(我不想使用通道)。但不知何故,我的答案并不正确。我尝试了两种方法。将指针传递给切片并传递切片本身。我不是在寻找全局锁变量。

    方法1(传递指针)

    type locks_block struct {
        population int
        mux sync.Mutex
    }
    
    func incr(ar *[] locks_block){
    
        for i:=0;i<len(*ar);i++ {
    
            (*ar)[i].mux.Lock()
            (*ar)[i].population = (*ar)[i].population+1;
            (*ar)[i].mux.Unlock()
    
        }
    }
    
    func main() {
    
        arr := make([]locks_block,5);
    
        go incr(&arr);
        go incr(&arr);
        go incr(&arr);
        go incr(&arr);
    
    
        fmt.Println(arr);
    }
    

    方法2(通过切片)

    type locks_block struct {
        population int
        mux sync.Mutex
    }
    
    func incr(ar [] locks_block){
    
        for i:=0;i<len(ar);i++ {
    
            ar[i].mux.Lock()
            ar[i].population = ar[i].population+1;
            ar[i].mux.Unlock()
    
        }
    }
    
    func main() {
    
        arr := make([]locks_block,5);
    
        go incr(arr);
        go incr(arr);
        go incr(arr);
        go incr(arr);
    
    
        fmt.Println(arr);
    }
    

    无论哪种情况,输出都不正确。

    1 回复  |  直到 6 年前
        1
  •  1
  •   aerth Prevok    6 年前

    看起来您正在正确使用锁,但在打印之前没有等待goroutines“完成” arr .尝试添加一个小 <-time.After(time.Second) ,或使用WaitGroup,或使用 select 等待所有Goroutine完成,或放置 fmt.Println(ar[i].population) 在goroutines内查看您想要看到的结果!

    如果你只是开始一系列的goroutines而不等待它们完成,同样的事情也会发生。

    这里是一个完整的工作示例,为了清晰起见,每个goroutine都有一个额外的“id”。请注意,goroutines的顺序不一致!

    package main
    
    import (
        "fmt"
        "sync"
        "time"
    )
    
    type locks_block struct {
        population int
        mux        sync.Mutex
    }
    
    func incr(id int, ar []locks_block) {
        for i := 0; i < len(ar); i++ {
            ar[i].mux.Lock()
            ar[i].population = ar[i].population + 1
            fmt.Printf("goroutine #%v, population   %v\n", id, ar[i].population)
            ar[i].mux.Unlock()
        }
    }
    
    func main() {
        arr := make([]locks_block, 5)
        go incr(1, arr)
        go incr(2, arr)
        go incr(3, arr)
        go incr(4, arr)
    
        // this should give the goroutines enough time
        <-time.After(time.Millisecond * 500)
        fmt.Println(arr)
    }