当前位置:网站首页>Go language core 36 lectures (go language practice and application VI) -- learning notes
Go language core 36 lectures (go language practice and application VI) -- learning notes
2022-06-24 01:33:00 【Zhengziming】
28 | Condition variables, sync.Cond ( Next )
problem 1: Conditional variable Wait What does the method do ?
After knowing how to use conditional variables , You may have a few questions .
1、 Why lock the mutex based on conditional variables first , To call its Wait Method ?
2、 Why use for Statement to wrap and call its Wait Method , use if Can't you ?
I often ask these questions during the interview . You need to be careful about this Wait Only when we understand the internal mechanism of the method can we answer .
Conditional variable Wait The method mainly does four things .
1、 Call it goroutine( It's the current goroutine) Add to the notification queue of the current condition variable .
2、 Unlock the mutex on which the current condition variable is based .
3、 Let the current goroutine In a waiting state , Wait until the notice arrives and decide whether to wake it up . here , This goroutine It's blocking the call to this Wait On the line of the method .
4、 If the notice comes and decides to wake this up goroutine, Then, after it is awakened, the mutex on which the current condition variable is based is locked again . Since then , Current goroutine It will continue to execute the following code .
Do you know the answer to the first question I just said now ?
Because the conditional variable Wait Method is blocking the current goroutine Before , Will unlock the mutex on which it is based , So call this Wait Before method , We have to lock the mutex first , Otherwise, call this Wait When the method is used , Will trigger an unrecoverable panic.
Why do conditional variables Wait How to do this ? You can imagine , If Wait Method when the mutex is locked , Blocking the current goroutine, So who will unlock it ? other goroutine Do you ?
Not to mention, this violates the important use principle of mutex , namely : Lock and unlock in pairs , Even if something else goroutine You can unlock , What if the unlock is repeated ? The result is panic But it can't be recovered .
If the current goroutine Can't unlock , other goroutine Not to unlock , So who will enter the critical zone , And change the state of shared resources ? As long as the state of shared resources remains unchanged , Even if the current goroutine Awakened by notice , Will still execute this again Wait Method , And blocked again .
So , If the conditional variable Wait Method without unlocking the mutex first , Then there are only two consequences : Not the current program because panic And collapse , It's related goroutine Total blocking .
Explain the second question . Obviously ,if Statement checks the state of the shared resource only once , and for Statement can be checked many times , Until this state changes . So why do you have to do multiple checks ?
This is mainly to be on the safe side . If one goroutine Awakened by notice , But it turns out that the state of shared resources , Still not up to its requirements , Then you should call the conditional variable again Wait Method , And continue to wait for the next notice .
This is very likely to happen , See below for details . There are many. goroutine Waiting for the same state of shared resources . such as
1、 There are many. goroutine Waiting for the same state of shared resources . such as , They are all waiting mailbox The value of the variable is not 0 Then change its value to 0, It's like there are many people waiting for me to put information into the mailbox . Although waiting goroutine There are many. , But every time you succeed goroutine But there can only be one . Don't forget , Conditional variable Wait Method will be in the current goroutine When you wake up, lock the mutex again . In the successful goroutine After finally unlocking the mutex , Other goroutine Will successively enter the critical zone , But they will find that the state of shared resources is still not what they want . This is the time ,for Circulation is necessary .
2、 Shared resources may not have two states , But more . such as ,mailbox The possible values of variables are not only 0 and 1, also 2、3、4. In this case , Because the result of each state change can only have one , therefore , On the premise of reasonable design , A single result must not satisfy all goroutine Conditions . The unsatisfied goroutine Obviously, we still need to wait and check .
3、 There is a possibility , There are only two states of shared resources , And each state has only one goroutine Paying attention to , Just like the example we implemented in the main problem . however , Even so , Use for Statements are still necessary . as a result of , In some more CPU In the core computer system , Even if you don't receive notification of the condition variable , Call its Wait Methodical goroutine It is also possible to be awakened . This is determined by the computer hardware level , Even the operating system ( such as Linux) The same is true for the condition variables provided by itself .
in summary , In the package condition variable Wait Method time , We should always use for sentence .
Okay , Come here , About conditional variables Wait Method , I think you know enough .
problem 2: Conditional variable Signal Methods and Broadcast What are the similarities and differences ?
Conditional variable Signal Methods and Broadcast Methods are used to send notifications , The difference is , The notification of the former will only wake up a waiting goroutine, The latter's notification will wake up all those waiting for it goroutine.
Conditional variable Wait Methods always put the current goroutine Add to the tail of the notification queue , And its Signal Methods always start at the head of the notification queue , Find wakeable goroutine. therefore , because Signal Method notice , And awakened goroutine It's usually the first one to wait .
The behavior of these two methods determines their applicable scenarios . If you're sure there's only one goroutine Waiting for notification , Or just wake up any one goroutine You can meet the requirements , So, using conditional variables Signal Just the way .
otherwise , Use Broadcast The method is always right , As long as you set up each goroutine The desired shared resource state is OK .
Besides , Again , And Wait The method is different , Conditional variable Signal Methods and Broadcast Methods do not need to be executed under the protection of a mutex . On the contrary , We'd better unlock the mutex on which the conditional variable is based , Then call its two methods . This is more conducive to the efficiency of the program .
Last , Please note that , The notification of conditional variables is immediate . in other words , If the notification is not sent goroutine Wait for , Then the notice will be discarded directly . After that, I began to wait goroutine Can only be awakened by a later notification .
You can open it demo62.go file , And watch it closely with demo61.go Different . In especial lock The type of variable , And how to send the notice .
package main
import (
"log"
"sync"
"time"
)
func main() {
// mailbox On behalf of mailbox .
// 0 Means the mailbox is empty ,1 Means the mailbox is full .
var mailbox uint8
// lock Represents the lock on the mailbox .
var lock sync.Mutex
// sendCond Represents a conditional variable dedicated to sending messages .
sendCond := sync.NewCond(&lock)
// recvCond Represents a conditional variable dedicated to receiving messages .
recvCond := sync.NewCond(&lock)
// send Represents the function used for sending messages .
send := func(id, index int) {
lock.Lock()
for mailbox == 1 {
sendCond.Wait()
}
log.Printf("sender [%d-%d]: the mailbox is empty.",
id, index)
mailbox = 1
log.Printf("sender [%d-%d]: the letter has been sent.",
id, index)
lock.Unlock()
recvCond.Broadcast()
}
// recv Represents the function used for receiving messages .
recv := func(id, index int) {
lock.Lock()
for mailbox == 0 {
recvCond.Wait()
}
log.Printf("receiver [%d-%d]: the mailbox is full.",
id, index)
mailbox = 0
log.Printf("receiver [%d-%d]: the letter has been received.",
id, index)
lock.Unlock()
sendCond.Signal() // Make sure there's only one sender goroutine.
}
// sign Used to signal the completion of the demonstration .
sign := make(chan struct{}, 3)
max := 6
go func(id, max int) { // For sending letters .
defer func() {
sign <- struct{}{}
}()
for i := 1; i <= max; i++ {
time.Sleep(time.Millisecond * 500)
send(id, i)
}
}(0, max)
go func(id, max int) { // For receiving letters .
defer func() {
sign <- struct{}{}
}()
for j := 1; j <= max; j++ {
time.Sleep(time.Millisecond * 200)
recv(id, j)
}
}(1, max/2)
go func(id, max int) { // For receiving letters .
defer func() {
sign <- struct{}{}
}()
for k := 1; k <= max; k++ {
time.Sleep(time.Millisecond * 200)
recv(id, k)
}
}(2, max/2)
<-sign
<-sign
<-sign
}summary
Today we mainly talk about conditional variables , It is a synchronization tool based on mutex . stay Go In language , We need to use sync.NewCond Function to initialize a sync.Cond Conditional variables of type .
sync.NewCond The function needs a sync.Locker Parameter value of type .
sync.Mutex Type and sync.RWMutex All values of type can satisfy this requirement . in addition , Latter RLocker Method can return the read lock in this value , It can also be used as sync.NewCond The parameter value of the function , In this way, the condition variable corresponding to the read lock in the read-write lock can be generated .
Conditional variable Wait Method needs to be executed under the protection of the mutex on which it is based , Otherwise, it will cause irrecoverable panic. Besides , We'd better use for Statement to check the state of the shared resource , And encapsulate the conditional variables Wait Method call .
Do not use if sentence , Because it can't be repeated “ Check status - Wait for a notice - Awakened ” It's the process of . The reason for repeating this process is , One “ Because waiting for notice , And blocked ” Of goroutine, May be awakened when the state of the shared resource does not meet its requirements .
Conditional variable Signal Method will only wake up a goroutine, And its Broadcast Method can wake up all those who are waiting for it goroutine. The latter is much more adaptable than the former .
These two methods do not need to be protected by mutex , We'd better not call them before we unlock the mutex . also , The notification of conditional variables is immediate . When the notification is sent , If there isn't any goroutine Need to be awakened , Then the notice will lapse immediately .
Thinking questions
sync.Cond Public fields in type L What is it for ? Can we change the value of this field during the use of conditional variables ?
Note source code
边栏推荐
- CLB O & M & operation best practices - big insight into access logs
- Selenium crawls stocks in practice
- 【Flutter】如何使用Flutter包和插件
- CSDN articles crawl the top ten bloggers' articles and convert them to MD
- The dispute between traditional IT development and low code development is heated, and the technical development rules may be restructured?
- [technology planting grass] talk about the system design and architecture of large-scale shopping platform
- How to create a group on a barcode label
- What is the relationship between the Internet of things and artificial intelligence?
- DCOM horizontal movement of Intranet penetration
- Esp8266 OTA remote and wireless upgrade
猜你喜欢
随机推荐
Salesforce uses hyperlink formula field to implement custom jump
Batch generation of 2D codes from txt files
S2b2c e-commerce platform in the pharmaceutical and medical industry enables enterprises to grasp differentiated competitive advantages and improve supply chain efficiency
Use Navicat software to connect self built database (Linux system)
November 17, 2021: the longest path of the same value. Given a binary tree, find the longest path
How to open Tencent enterprise mailbox and Tencent enterprise mailbox login portal
Remove the cloud disk service display "continued" logo
Selenium crawls stocks in practice
Video stream playback address redirection optimization after easycvr replaces the new kernel
Dart series part: asynchronous programming in dart
Technology sharing | Clickhouse cluster's way of expanding replicas under sharding
Millions of routers are at risk of attack, and hackers supported by North Korea are invading the United States and Britain | November 19 global network security hotspot
Echo framework: implementing distributed log tracing
Eight common errors in programming
How to select storage space for website construction what factors should be considered in selecting space
The best Base64 encoding and decoding tutorial in the whole network, with 6 examples!
Common e-commerce data index system
How does Huawei weautomate RPA achieve the natural growth of government enterprise automation?
[technical grass planting] cdn+ lightweight server +hugo= let the blog "cloud native"
What is the website construction process? What details need to be valued?

