Golang实现任意个哲学家就餐问题

Countingstarss · · 782 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

Golang实现任意个哲学家就餐问题

《现代操作系统》中方法

package main

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

func main() {
    run := func(philoCnt int) { //开始执行i个哲学家就餐
        var (
            thinging = 0
            hungry   = 1
            eating   = 2
        )
        mutex := sync.Mutex{}
        philoMutex := make([]sync.Mutex, philoCnt)
        state := make([]int, philoCnt)

        for i := range philoMutex {
            philoMutex[i].Lock() //先全部上锁
        }

        leftPos := func(i int) int {
            return (philoCnt + i - 1) % philoCnt
        }
        rightPos := func(i int) int {
            return (philoCnt + i + 1) % philoCnt
        }

        test := func(i int) {
            if state[i] == hungry && state[leftPos(i)] != eating && state[rightPos(i)] != eating {
                state[i] = eating
                philoMutex[i].Unlock()
            }
        }

        getForks := func(i int) {
            mutex.Lock()
            state[i] = hungry
            test(i)
            mutex.Unlock()
            philoMutex[i].Lock()
        }

        putForks := func(i int) {
            mutex.Lock()
            state[i] = thinging
            test(leftPos(i))
            test(rightPos(i))
            mutex.Unlock()
        }

        philosopher := func(i int) {
            for {
                time.Sleep(time.Second) //think

                getForks(i)
                time.Sleep(time.Second) //eat
                putForks(i)
            }
        }

        //部署i个哲学家
        for i := 0; i < philoCnt; i++ {
            go philosopher(i)
        }

        //监视进程,用来显示就餐情况
        func() {
            for {
                mutex.Lock()
                fmt.Println(state)
                mutex.Unlock()
                time.Sleep(100 * time.Millisecond)
            }
        }()
    }
    run(5)
}

​ 程序输出为每100ms输出各个哲学家的状态,结果如下:

image-20201226165910301.png

只利用一个互斥锁的方法

package main

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

func main() {
    var (
        thinking = 0
        hungry   = 1
        eating   = 2
    )

    run := func(philoCnt int) {
        mutex := sync.RWMutex{}
        state := make([]int, philoCnt)
        for i := range state {
            state[i] = thinking
        }

        leftPos := func(i int) int {
            if i == 0 {
                return philoCnt - 1
            }
            return i - 1
        }
        rightPos := func(i int) int {
            if i == philoCnt-1 {
                return 0
            }
            return i + 1
        }

        protectTest := func(i int) bool {
            if state[leftPos(i)] == eating || state[rightPos(i)] == eating {
                return false
            }
            state[i] = eating
            return true
        }
        test := func(i int) bool {
            mutex.Lock()
            defer mutex.Unlock()
            if state[leftPos(i)] == eating || state[rightPos(i)] == eating {
                return false
            }
            state[i] = eating
            return true
        }

        getForks := func(i int) {
            mutex.Lock()
            state[i] = hungry
            mutex.Unlock()

            for test(i) == false {
            }
        }

        putForks := func(i int) {
            mutex.Lock()
            defer mutex.Unlock()
            state[i] = thinking
            protectTest(leftPos(i))
            protectTest(rightPos(i))
        }

        philosopher := func(i int) {
            for {
                time.Sleep(time.Second)
                getForks(i)
                time.Sleep(time.Second)
                putForks(i)
            }
        }

        for i := 0; i < philoCnt; i++ {
            go philosopher(i)
        }

        func() {
            for {
                mutex.RLock()
                eatingCnt := 0
                for _, val := range state {
                    if val == eating {
                        eatingCnt++
                    }
                }
                fmt.Println(eatingCnt, state)
                mutex.RUnlock()
                time.Sleep(100 * time.Millisecond)
            }
        }()
    }
    run(5)
}

​ 程序输出为每100ms输出各个哲学家的状态,结果如下:

image-20201226170125722.png

有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:Countingstarss

查看原文:Golang实现任意个哲学家就餐问题

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

782 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传