douguluan5102 2018-12-12 12:33
浏览 55
已采纳

通过锁询问时间同步获取锁

I have a program with a goroutine that we will call mainRoutine which lock a ressource, on the other side other goroutines of fired which we will name goroutine-0 goroutine-1 goroutine-2 .... this routine try to acquire the lock, after the mainRoutine stop I need my other goroutine to acquire the lock in a synchronized way, what I mean is that I want the goroutine-0 then goroutine-1 ... What I've done to face this problem is a slice of time.Time that is populate with the time.Now() at which the goroutine was launched, and made use of sync.Cond. Some code example to illustrate:

package main

import (
    "fmt"
    "sync"
    "time"
)

func condition(myTime time.Time, timeSlice []time.Time) bool {
    for _, v := range timeSlice {
        if myTime.After(v) {
            return false
        }
    }
    return true
}

func removeFromSlice(myTime time.Time, timeSlice []time.Time) {
    var place int
    for i, v := range timeSlice {
        if myTime.Equal(v) {
            place = i
            break
        }
    }

    timeSlice = append(timeSlice[:place], timeSlice[place+1:]...)
}

func main() {
    var m sync.Mutex
    c := sync.NewCond(&m)

    c.L.Lock()
    fmt.Println("Locker locked")
    go func() {
        time.Sleep(time.Second * 1)

        c.L.Unlock()
        fmt.Println("Locker unlocked")
    }()

    var wg sync.WaitGroup
    var timeSlice []time.Time
    wg.Add(100)

    for i := 0; i < 100; i++ {
        now := time.Now()
        timeSlice = append(timeSlice, now)
        time.Sleep(time.Nanosecond * 1) // ensure there's at leat 1 nanosec of diff between 2 time.Now
        go func(i int, myTime time.Time) {
            fmt.Printf("Before %d %d
", i, myTime.Unix())
            c.L.Lock()
            for !condition(myTime, timeSlice) {
                c.Wait()
            }
            c.L.Unlock()
            removeFromSlice(myTime, timeSlice)
            c.Broadcast()
            wg.Done()
            fmt.Printf("After done %d
", i)
        }(i, now)
    }
    wg.Wait()

    fmt.Println("Hello, playground")
}

I don't think it's the right way to do this kind of thing it seems really hacky, is there a better way?

-- EDIT -- After the answer of @Vorsprung I think the best approach in my case is making a slice of func which always call the 1st elem of the slice

package main

import (
    "fmt"
    "sync"
)

func makeFunc(id int) func() {
    return func() {
        fmt.Printf("called %d
", id)
    }
}

func main() {
    var wg sync.WaitGroup
    var funcSlice []func()
    var m sync.Mutex

    for i := 0; i < 5; i++ {
        funcSlice = append(funcSlice, makeFunc(i))
        wg.Add(1)
        go func() {
            defer wg.Done()
            m.Lock()
            defer m.Unlock()
            funcSlice[0]()
            funcSlice = funcSlice[1:]
        }()
    }
    wg.Wait()
    fmt.Println("finished")
}
  • 写回答

1条回答 默认 最新

  • donglun1020 2018-12-12 14:03
    关注

    Give the goroutines an internal id and then get them to call each other in sequence. Example of how this might work below

    package main
    
    import (
        "fmt"
        "sync"
    )
    
    func main() {
        var wg sync.WaitGroup
        var c [5]chan int
        for i := range c {
            c[i] = make(chan int)
            wg.Add(1)
            go func(id int) {
                defer wg.Done()
                f := <-c[id]
                fmt.Println("called from ", f, ".  My id ", id)
                if id < 4 {
                    fmt.Println(id+1, " next")
                    c[id+1] <- id
                }
                fmt.Println("ending ", id)
            }(i)
        }
        c[0] <- 99
    
        wg.Wait()
        fmt.Println("bye")
    }
    

    https://play.golang.org/p/psF8ISodJU_3

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 怎样才能让鼠标沿着线条的中心线轨迹移动
  • ¥60 用visual studio编写程序,利用间接平差求解水准网
  • ¥15 Llama如何调用shell或者Python
  • ¥20 谁能帮我挨个解读这个php语言编的代码什么意思?
  • ¥15 win10权限管理,限制普通用户使用删除功能
  • ¥15 minnio内存占用过大,内存没被回收(Windows环境)
  • ¥65 抖音咸鱼付款链接转码支付宝
  • ¥15 ubuntu22.04上安装ursim-3.15.8.106339遇到的问题
  • ¥15 blast算法(相关搜索:数据库)
  • ¥15 请问有人会紧聚焦相关的matlab知识嘛?