Use of variable conditions and principles go

Scenes

Recently a scenario encountered when writing the code necessary to use map [int] struct {} structure to store task, the key is the task of the Map id, it can be increased or decreased at any time. In addition to reading books because it is really, basically never used condition variable so the back after a day can only think of the condition variable to achieve. I remember an article on the blog to see the words very good, probably the synchronized statement, the characteristic condition variable is waiting.

A start code something like this

Event Loop

func Loop() {
    for {
        mutex.Lock()
        for taskId, task := range tasks {
            // handle code
        }
        lenght := len(task)
        mutex.UnLock()

        // 为了减少cpu空转  当队列为空的时候sleep 2秒
        if length == 2 {
            time.Sleep(time.Secord * 2)
        }
    }
}   

New task (delete is similar)

func addTask(t *Task) {
    mutex.Lock()
    tasks[t.Id] = t
    mutex.UnLock()
}

Using Condition Variables

Event loop code after the variable conditions of use

func Loop() {
    for {
        mutex.Lock()
        // 如果当前任务数为0 调用Wait()等待新任务增加时唤醒
        if len(tasks) == 0 {
            cond.Wait() // cond := sync.NewCond(&mutex)
        }

        for taskId, task := range tasks {
            // handle code
        }
        mutex.UnLock()
    }
}

New task (task delete the code no change)

func addTask(t *Task) {
    mutex.Lock()
    tasks[t.Id] = t
    if len(task) == 1 {  // 从0->1 可能之前有goruntine阻塞
        cond.Signal()    // 由于Loop()是单协程在跑所以 使用的是Signal()足矣
    }
    mutex.UnLock()
}

Condition variable principles (language-independent)

If pthread_cond condition variable C language and GO main difference, or the difference between coroutines and true kernel threads in essence, go bag comes with sync condition variable operations goruntine, the blocking / wake do not need to fall into the kernel state.

Wait()

func (c *Cond) Wait() {
    c.checker.check()
    t := runtime_notifyListAdd(&c.notify)  // 等待的goruntine数+1
    c.L.Unlock() // 释放锁资源
    runtime_notifyListWait(&c.notify, t) // 阻塞,等待其他goruntine唤醒
    c.L.Lock() // 获取资源
}

Signa () and BroadCast ()

func (c *Cond) Signal() {
    c.checker.check()
    runtime_notifyListNotifyOne(&c.notify) // 唤醒最早被阻塞的goruntine
}

func (c *Cond) Broadcast() {
    c.checker.check()
    runtime_notifyListNotifyAll(&c.notify) // 唤醒所有goruntine
}

Guess you like

Origin www.cnblogs.com/Me1onRind/p/11653561.html