6

Critical Resource Definition

Resources shared by multiple processes, threads, and coroutines in a concurrent environment

Characteristics of Critical Resources

It may cause data inconsistency due to concurrent operations. For example, a in the following code is a timely critical resource

 package main

import (
    "fmt"
    "time"
)

func main() {
    //临界资源
    a := 1
    go func() {
        a = 2
        fmt.Println("in this goroutine: a is : ", a)
    }()
    //在主goroutine中
    a = 3
    time.Sleep(1)
    fmt.Println("in the main goroutine: a is : ", a)
}

The classic ticketing problem, the number of tickets sold in multiple windows at the same time is a typical critical resource security problem. Let’s use four coroutines to simulate the ticketing process:

 package main

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

var ticket = 10 //the amount of the total ticket is 100
func main() {
    //这里启动4个goroutine模拟4个售票口 同时售票
    go saleTickets("ticket window1")
    go saleTickets("ticket window2")
    go saleTickets("ticket window3")
    go saleTickets("ticket window4")
    //这里为了保证 主协程 最后执行完 先用sleep (当然,也可以用同步等待组、chanel实现)
    time.Sleep(10 * time.Second)
}

func saleTickets(name string) {
    rand.Seed(time.Now().UnixNano())
    for {
        if ticket > 0 {
            time.Sleep(time.Duration(rand.Intn(1000)) * time.Millisecond)
            fmt.Println(name, "saled: ", ticket)
            ticket--
        } else {
            fmt.Println(name, "sorry tickets are sold out")
            break
        }
    }
}

The results are as follows:

 ticket window3 saled:  10
ticket window1 saled:  9
ticket window4 saled:  8
ticket window2 saled:  7
ticket window3 saled:  6
ticket window2 saled:  5
ticket window1 saled:  4
ticket window1 saled:  3
ticket window4 saled:  2
ticket window2 saled:  1
ticket window2 sorry tickets are sold out
ticket window4 saled:  0
ticket window4 sorry tickets are sold out
ticket window3 saled:  -1
ticket window3 sorry tickets are sold out
ticket window1 saled:  -2
ticket window1 sorry tickets are sold out

There are actually -2 tickets sold here, which is obviously in addition to the problem, where is the problem?

  • Let's assume that there is only the last ticket left, and now the program is in the main coroutine
  • The coroutine of window 4 gets the cpu resources, reads the total number of remaining tickets to 1, and then sleeps to release the cpu resources
  • The coroutine of window 3 obtains the cpu resource, and finds that the total number of remaining tickets is 1 (because the coroutine of window 4 enters sleep, and the ticket is not modified before the cpu resource of window 3 is obtained), and then sleeps to release the cpu resource.
  • Window 4 wakes up, ticket = 1 - 1 = 0
  • Window 3 wakes up, ticket = 0 - 1 = -1
    In response to this problem, it can be solved by locking, allowing only one goroutine to access the shared data in a certain period of time. After the access is completed, other goroutines can only access it after unlocking.
    But what's interesting is that go does not encourage such a way to communicate in a shared way, but to share in a way of communication [that is, it is not encouraged to use sync packets to lock, and the use of chanel is encouraged]

Resource reference: bilibili


LiberHome
409 声望1.1k 粉丝

有问题 欢迎发邮件 📩 liberhome@163.com