條件變量和互斥鎖結合channel使用

package main

import (
    "fmt"
    "math/rand"
    "sync"
    "time"
)

var cond sync.Cond // 定義全局條件變量

func product(out chan<- int, index int) {
    for {
        // 先加鎖
        cond.L.Lock()
        // 判斷緩衝區是否滿
        for len(out) == 5 {
            // a)阻塞等待條件變量滿足
            // b)釋放已掌握的互斥鎖相當於cond.L.Unlock()。 注意:兩步爲一個原子操作。
            // c)當被喚醒,Wait()函數返回時,解除阻塞並重新獲取互斥鎖。相當於cond.L.Lock()
            cond.Wait()
        }
        num := rand.Intn(1000)
        out <- num
        fmt.Printf("生產者%dth,生產:%d\n", index, num)
        // 訪問公共區結束,並且打印結束,解鎖
        cond.L.Unlock()
        // 喚醒阻塞在條件變量上的 消費者
        cond.Signal()
        time.Sleep(time.Millisecond * 300)
    }
}

func consumer(in <-chan int, index int) {
    for {
        // 先加鎖
        cond.L.Lock()
        // 判斷 緩衝區是否爲空
        for len(in) == 0 {
            // a)阻塞等待條件變量滿足
            // b)釋放已掌握的互斥鎖相當於cond.L.Unlock()。 注意:兩步爲一個原子操作。
            // c)當被喚醒,Wait()函數返回時,解除阻塞並重新獲取互斥鎖。相當於cond.L.Lock()
            cond.Wait()
        }
        num := <-in
        fmt.Printf("----消費者%dth,消費:%d\n", index, num)
        // 訪問公共區結束後,解鎖
        cond.L.Unlock()
        // 喚醒 阻塞在條件變量上的 生產者
        cond.Signal()
        time.Sleep(time.Millisecond * 200)
    }
}

func main() {
    ch := make(chan int, 5)
    quit := make(chan bool)
    rand.Seed(time.Now().UnixNano())
    // 指定條件變量 使用的鎖
    cond.L = new(sync.Mutex)
    for i := 0; i < 5; i++ {
        go product(ch, i+1)
    }
    for i := 0; i < 5; i++ {
        go consumer(ch, i+1)
    }
    <-quit
}

打印:

生產者1th,生產:386
----消費者5th,消費:386
生產者3th,生產:975
----消費者1th,消費:975
生產者2th,生產:615
----消費者3th,消費:615
生產者4th,生產:207
生產者5th,生產:140
----消費者2th,消費:207
----消費者4th,消費:140

..................

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章