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
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。