美文网首页
Go 临界资源

Go 临界资源

作者: 来到了没有知识的荒原 | 来源:发表于2020-07-18 14:51 被阅读0次

出现临界资源访问问题的代码

package main

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

var ticket = 10

func main() {

    go sellTicket("售票口1")
    go sellTicket("售票口2")
    go sellTicket("售票口3")
    go sellTicket("售票口4")

    time.Sleep(3*time.Second)
}

func sellTicket(name string) {
    rand.Seed(time.Now().UnixNano())
    for {
        if ticket > 0 {
            time.Sleep(time.Duration(rand.Intn(1000))*time.Millisecond)
            fmt.Println(name, "售出", ticket)
            ticket--
        } else {
            break
        }
    }
}

不要以共享内存的方式去通信,而是以通信的方式共享内存

  • sync
  • 鼓励使用channel

使用waitgroup实现同步(信号量)

WaitGroup 同步等待组
Add() 设置等待组中goroutine的数量
Wait() 让当前gouroutine处于阻塞状态
Done() 让等待组中计数器减一

package main

import (
    "fmt"
    "sync"
)

var wg sync.WaitGroup

func main() {

    wg.Add(2)
    go fun1()
    go fun2()

    fmt.Println("main... 阻塞")
    wg.Wait()
    fmt.Println("main ... 完成")
}

func fun1() {
    for i := 0; i < 5; i++ {
        fmt.Println("func1 ", i)
    }
    wg.Done()
}

func fun2() {
    defer wg.Done()
    for i := 0; i < 5; i++ {
        fmt.Println("func2 ", i)
    }
}

当这段程序中wg.Add(2)改为wg.Add(3)的时候,就会因为计数器最终为1,main函数无法解除阻塞,产生死锁。

mutex解决一开始的临界资源访问问题

package main

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

var ticket = 10
var mutex sync.Mutex

func main() {

    go sellTicket("售票口1")
    go sellTicket("售票口2")
    go sellTicket("售票口3")
    go sellTicket("售票口4")

    time.Sleep(5 * time.Second)
}

func sellTicket(name string) {
    rand.Seed(time.Now().UnixNano())
    for {
        mutex.Lock()
        if ticket > 0 {
            time.Sleep(time.Duration(rand.Intn(1000)) * time.Millisecond)
            fmt.Println(name, "售出", ticket)
            ticket--
        } else {
            mutex.Unlock()
            fmt.Println("票卖完了...")
            break
        }
        mutex.Unlock()
    }
}

使用WaitGroup让main函数等待四个goroutine完成后再结束
(替代掉time.Sleep)

package main

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

var ticket = 10
var mutex sync.Mutex
var wg sync.WaitGroup

func main() {

    wg.Add(4)
    go sellTicket("售票口1")
    go sellTicket("售票口2")
    go sellTicket("售票口3")
    go sellTicket("售票口4")

    wg.Wait()
    fmt.Println("程序结束了")
}

func sellTicket(name string) {
    rand.Seed(time.Now().UnixNano())
    defer wg.Done()
    for {
        mutex.Lock()
        if ticket > 0 {
            time.Sleep(time.Duration(rand.Intn(1000)) * time.Millisecond)
            fmt.Println(name, "售出", ticket)
            ticket--
        } else {
            mutex.Unlock()
            fmt.Println("票卖完了...")
            break
        }
        mutex.Unlock()
    }
}

相关文章

  • Go 临界资源

    出现临界资源访问问题的代码 不要以共享内存的方式去通信,而是以通信的方式共享内存 sync 鼓励使用channel...

  • 进程的同步与互斥

    同步和互斥 临界资源 对多个进程或者线程都可见的资源,容易产生争夺,这类资源称为临界资源 临界区 对临界资源进行操...

  • 资源竞速(Race Conditions)和临界区(Critic

    临界区 临界区的资源竞速 避免资源竞速 临界区的吞吐量 critical section是每个线程中访问临界资源的...

  • SynChronized

    并发编程对共享资源,临界资源的访问 在并发编程中对临界资源的访问有可能出现并发问题,注意是临界资源,共享资源,普通...

  • 信号量机制和PV操作

    临界区资源互斥访问 进程管理中,对临界资源需要互斥访问。其中对实现对临界区互斥访问有软件和硬件方法。 软件方法包括...

  • 进程同步的几种方式

    每个进程中访问临界资源的那段程序称为临界区(临界资源是一次仅允许一个进程使用的共享资源)。每次只准许一个进程进入临...

  • 高并发基础知识详细讲解

    Synchronized synchronized锁哪些东西? this(指的是当前对象) 临界资源(锁的是临界资...

  • 开发十年,留下最完整的Java架构学习路线,学完年薪65W

    10. 解决临界资源问题之同步方法 11. 解决临界资源问题之ReentrantLock 12. 多线程讲解和理解...

  • 并发(2) -- synchronized 与 Lock

    临界资源 序列化访问共享资源,指给定时刻只允许一个任务可以访问到临界资源。 synchronized 在执行 sy...

  • 关于并发编程中临界资源的问题

    临界资源: 指并发环境中多个进程/线程共享的资源. 在并发编程中对临界资源的处理不当, 往往会导致数据不一致的问题...

网友评论

      本文标题:Go 临界资源

      本文链接:https://www.haomeiwen.com/subject/dntfkktx.html