当前位置:网站首页>[rust notes] 17 concurrent (Part 2)
[rust notes] 17 concurrent (Part 2)
2022-07-05 06:05:00 【phial03】
17.3 - Share modifiable state
17.3.1 - The mutex
The mutex ( Or lock ): Used to force multiple threads to access specific data in turn .
C++ Implementation example of mutual exclusion of :
void FernEngine::JoinWaitingList(PlayerId player) { mutex.Acquire(); // A critical region (critical section): Start waitingList.push_back(player); // If the waiting player meets the conditions, start the game if (waitingList.length() >= GAME_SIZE) { vector<PlayerId> players; waitingList.swap(players); StartGame(players); } mutex.Release(); // A critical region (critical section): end }
The role of mutexes :
- Prevent data contention , Avoid multiple threads reading and writing the same block of memory concurrently .
- Prevent the operations of different threads from interleaving .
- Mutexes support invariance (invariant) Programming , The protected data is initialized by the performer , Maintained by each critical zone .
17.3.2-Mutex<T>
Rust The protected data in is stored in
Mutex
Inside :let app = Arc::new(FernEmpireApp { // Create the entire application , Distributed on the heap ... waiting_list: Mutex::new(vec![]), ... });
Arc
It is convenient to share data across threads .Mutex
It is convenient to share modifiable data across threads .
give an example : Use mutex
impl FernEmpireApp { fn join_waiting_list(&self, player: PlayerId) { let mut guard = self.waiting_list.lock().unwrap(); guard.push(player); if guard.len() == GAME_SIZE { let players = guard.split_off(0); self.start_game(players); } } }
The only way to get the data of the mutex is to call
.lock()
Method .At the end of the jam ,
guard
After being cleared , The lock will also be released . But it can also be removed manually :if guard.len() == GAME_SIZE { let players = guard.split_off(0); drop(guard); self.start_game(players); }
17.3.3-mut
And Mutex
mut
: Means proprietary 、 Exclusive access (exclusive access).- Not
mut
: Means shared access (shared access). Mutex
The mutex , Provide proprietary access to datamut
Access right , Even if many threads are rightMutex
Own sharing ( Notmut
) Access right .- Rust Compiler at compile time , Proprietary access can be dynamically controlled through the type system .
17.3.4 - The problem of mutex
- Only rely on “ Parallel bifurcation — Merge ” The procedure is deterministic , It's impossible to deadlock .
- Procedures that specifically use channels to achieve pipeline operations are also deterministic , Although the time of message transmission may be different , But it will not affect the output .
- Data contention : Concurrent reading of the same block of memory by multiple threads leads to meaningless results . Safe Rust Code does not trigger data contention .
- There may be a problem with mutexes :
- Effective Rust There will be no data contention in the program , But there may still be race conditions (race condition), That is, the program behavior depends on the execution time of the thread , Therefore, the results of each run may be different . Using mutexes in an unstructured way can lead to race conditions .
- Shared modifiable state will affect program design . Channels can be used as abstract boundaries in code . Mutexes encourage the addition of a method to solve the problem , May cause code entanglement , Difficult to peel off .
- The implementation of mutex is more complex .
- Use structured programming whenever possible , Use mutexes when necessary
Mutex
.
17.3.5 - Deadlock
Threads may cause deadlocks when trying to read locks they already hold .
let mut guard1 = self.waiting_list.lock().unwrap(); let mut guard2 = self.waiting_list.lock().unwrap(); // Deadlock
Using channels can also lead to deadlocks . For example, two threads block each other , Each waits to receive a message from the other .
17.3.6 - Poisoned mutex
If the thread is holding
Mutex
I was surprised , that Rust Will
Mutex
Mark as poisoned .
- Later, I want to lock the contaminated
Mutex
All attempts will get a wrong result . .unwrap()
Call to tell Rust In this case, be surprised , Propagate the surprise of other threads to the current thread .- Surprised threads ensure that the rest of the program is in a safe state .
- Later, I want to lock the contaminated
Rust Poison this mutex to prevent other threads from inadvertently doing the same .
- In the case of complete mutual exclusion , It can lock the poisoned mutex , Access the data in it at the same time .
- See
PoisonError::into_inner()
.
17.3.7 - Multi consumer channels using mutexes
There is only one channel
Receiver
.No thread pool can have multiple threads using one
mpsc
Channel sharing succeeded .An exceptional way to bypass this limitation : It can be for
Receiver
Add oneMutex
, Then share .pub mod shared_channel { use std::sync::{ Arc, Mutex}; use std::sync::mpsc::{ channel, Sender, Receiver}; /// Yes Receiver Thread safe encapsulation #[derive(Clone)] pub struct SharedReceiver<T>(Arc<Mutex<Receiver<T>>>); // Arc<Mutex<Receiver<T>>> Is a nested generic impl <T> Iterator for SharedReceiver<T> { type Item = T; /// Get the next item from the encapsulated recipient fn next(&mut self) -> Option<T> { let guard = self.0.lock().unwrap(); guard.recv().ok() } } /// Create a new channel , Its recipients can share across threads . /// Return a sender and a receiver , And stdlib Of channel() similar . /// Sometimes it can be used directly instead of it . pub fn shared_channel<T>() -> (Sender<T>, SharedReceiver<T>) { let (sender, receiver) = channel(); (sender, SharedReceiver(Arc::new(Mutex::new(receiver)))) } }
17.3.8 - Read write lock and RwLock<T>
Mutex uses
lock
Method to read and write data .The read-write lock uses
read
andwrite
There are two ways to read and write data .RwLock::write
Method : AndMutex::lock
similar , Are waiting to get proprietary information about protected datamut
visit .RwLock::read
Method provides nonmut
visit , There's almost no need to wait , Because multiple threads can read data safely at the same time .
The difference between mutex and read-write lock :
- At any given moment , Protected data can only have one reader or writer .
- When a read-write lock is used , There can be one writer or multiple readers , Be similar to Rust quote .
- It is preferred to use read-write lock , Not mutexes .
Optimize the above
FernEmpireApp
Program :Create a structure to save configuration information , And by the
RwLock
Protect .use std::sync::RwLock; struct FernEmpireApp { ... config: RwLock<AppConfig>, ... }
The method of reading this configuration can use
RwLock::read()
:fn mushrooms_enabled(&self) -> bool { let config_guard = self.config.read().unwrap(); config_guard.mushrooms_enabled }
How to reload this configuration , Then use
RwLock::write()
:fn reload_config(&self) -> io::Result<()> { let new_config = AppConfig::load()?; let mut config_guard = self.config.write().unwrap(); *config_guard = new_config; Ok(()) }
self.config.read()
Return to a guard , Can provide forAppConfig
Non -mut
( Sharing ) visit ;self.config.write()
Return a different type of guard , Can providemut
( Proprietary ) visit .
17.3.9 - Condition variables, (Condvar
)
A thread often needs to wait for a condition to become
true
:
- During server shutdown , The main thread may need to wait for all other threads to exit completely .
- When the worker thread is idle , You need to wait for the data to be processed .
- Threads that implement distributed consensus protocols , You need to wait for enough peer threads to respond .
For conditions that require waiting , There will be convenient blockage API, without , Then you can use conditional variables (condition variable) To build your own API.
std::sync::Condvar
Type implements conditional variables .- its
.wait()
Method can block some threads to call its.notify_all()
.
Mutex
AndCondvar
There is a direct connection : The conditional variable always represents by someMutex
Protected data or true or false conditions .
17.3.10 - Type of atom
std::sync::atomio
The module contains the atomic types used in lock free concurrent programming .
AtomicIsize
andAtomicUsize
: Is a shared integer type , Corresponding to single threadisize
andusize
type .AtomicBool
: It's a sharedbool
value .AtomicPtr<T>
: Is an unsafe pointer type*mut T
Shared value of .
The simplest application of atoms is to cancel operations . Suppose there is a thread performing some time-consuming computation of any , Such as rendering video , We hope to cancel this operation asynchronously . Then you can use a shared
AtomicBool
To achieve . Render every pixel , Threads will call.load()
Method to check the value of the cancel flag .Atomic operations never use system calls . Loading and storage will be compiled into a CPU Instructions .
atom 、
Mutex
、RwLock
You can useself
The shared reference of is a parameter . They can also be used as simple global variables .
17.3.11 - Global variables
- For global variables : Thread safety must be guaranteed in some way . Static variables must be both
Sync
, Right and wrong againmut
. - Static initializers cannot call functions . have access to
lazy_staic
Package to achieve .
See 《Rust Programming 》( Jim - Brandy 、 Jason, - By orendov , Translated by lisongfeng ) Chapter 19
Original address
边栏推荐
- 1.13 - RISC/CISC
- 2022年貴州省職業院校技能大賽中職組網絡安全賽項規程
- 从Dijkstra的图灵奖演讲论科技创业者特点
- How to adjust bugs in general projects ----- take you through the whole process by hand
- CPU内核和逻辑处理器的区别
- MIT-6874-Deep Learning in the Life Sciences Week 7
- Bit mask of bit operation
- CF1634 F. Fibonacci Additions
- Implement a fixed capacity stack
- Data visualization chart summary (II)
猜你喜欢
Solution to game 10 of the personal field
CF1637E Best Pair
LeetCode 0108.将有序数组转换为二叉搜索树 - 数组中值为根,中值左右分别为左右子树
QQ computer version cancels escape character input expression
Codeforces round 712 (Div. 2) d. 3-coloring (construction)
个人开发的渗透测试工具Satania v1.2更新
实时时钟 (RTC)
Sword finger offer 53 - I. find the number I in the sorted array
Some common problems in the assessment of network engineers: WLAN, BGP, switch
网络工程师考核的一些常见的问题:WLAN、BGP、交换机
随机推荐
Daily question 1342 Number of operations to change the number to 0
wordpress切换页面,域名变回了IP地址
【Rust 笔记】16-输入与输出(上)
1040 Longest Symmetric String
[jailhouse article] jailhouse hypervisor
Light a light with stm32
Introduction et expérience de wazuh open source host Security Solution
Daily question 2006 Number of pairs whose absolute value of difference is k
2022 极术通讯-Arm 虚拟硬件加速物联网软件开发
leetcode-6111:螺旋矩阵 IV
个人开发的渗透测试工具Satania v1.2更新
Data visualization chart summary (I)
Annotation and reflection
可变电阻器概述——结构、工作和不同应用
【实战技能】非技术背景经理的技术管理
Transform optimization problems into decision-making problems
How to adjust bugs in general projects ----- take you through the whole process by hand
Sword finger offer 53 - ii Missing numbers from 0 to n-1
One question per day 1447 Simplest fraction
Daily question - longest substring without repeated characters