惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Martin Fowler
Martin Fowler
Y
Y Combinator Blog
M
MIT News - Artificial intelligence
The Cloudflare Blog
WordPress大学
WordPress大学
H
Hackread – Cybersecurity News, Data Breaches, AI and More
博客园 - 司徒正美
小众软件
小众软件
Blog — PlanetScale
Blog — PlanetScale
雷峰网
雷峰网
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
J
Java Code Geeks
云风的 BLOG
云风的 BLOG
C
Check Point Blog
D
DataBreaches.Net
T
The Blog of Author Tim Ferriss
V
V2EX
F
Fortinet All Blogs
B
Blog
大猫的无限游戏
大猫的无限游戏
N
Netflix TechBlog - Medium
B
Blog RSS Feed
A
About on SuperTechFans
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC

Whexy Blog

关于身体 替尔泊肽 We lost the AIxCC. So, what now? Arm VMM with Apple's Hypervisor Framework Driving WaveShare E‐Paper Display with a Raspberry Pi Pico in MicroPython Use cgroup v2 inside docker containers Annual Hit Piece: Fuzzing Top Conference Paper Debunking Report Solving SSH Key Login Issues on Synology NAS Can SSD Cache Improve Synology NAS Write Speeds? Virtualization is all you need Running Windows Games on Mac Without Virtual Machines Tears of the Kingdom: End of an Era Anonymous CDN Traffic Relay Self-host Relay Service with CDN Home Networking Solution Building Your Own Blog System Connecting Smart Devices to SUSTech Campus Network Function Color Theory Stop Forkin' Around: Faster Creating of Large Processes on Linux PMU Interrupts: How to handle them Using QEMU to run Linux images on M1 Macbook Alligator In Vest - My first research work Experience Using Several Plugins in Complex LaTeX Projects Variance in Rust Understanding Rust Generic Traits SUSTeam: Ultimate Gaming Platform Inline Assembly Language in C React Learning Notes Building a School Bus Schedule App for Apple Watch 12307 Train Ticket Purchase Platform
Asynchronous Mutex
Whexy · 2021-09-05 · via Whexy Blog

Whexy /

September 05, 2021

Asynchronous programs can also be applied on multi-thread system through "thread pool". However, using mutex in it might be a problem.

Here is the example from Jon Gjengset's live stream "Crust of Rust: async/await".

async fn main() {
  let x = Arc::new(Mutex::new(0));
  let x1 = Arc::clone(&x);
  tokio::spawn(async move {
    loop {
      let x = x1.lock();
      tokio::fs::read_to_string("file").await;
      *x += 1;
      // the lock of x is automatically droped here
    }
  });
  let x2 = Arc::clone(&x);
  tokio::spawn(async move {
    loop {
      *x2.lock() -= 1;
    }
  });
}

Two spawned asynchronous functions are going to change the value in x.

Using spawn allows us to execute the asynchronous functions simultaneously (creating two event loops). Thus we must use Mutex to protect the value of x. But spawn may not give us another thread to run the program since it is "smart". It will decide whether to create another thread to do that or still using the existing one.

Let's say this time; the spawn decides to run the program in just one thread. When the line 7 tokio::fs::read_to_string("file").await; gets executed, the function will yield and get back to the executor (tokio runtime). Then, the executor decides to execute the function in line 15 *x2.lock() -= 1;. Now we encounter a deadlock. The control flow looks like this.

let x = x1.lock(); // async func 1 get the lock
tokio::fs::read_to_string("file").await; // func 1 yields!

// tokio runtime stores the context and switch to func 2

*x2.lock() -= 1; // async func 2 tries to get the lock but fails;
// the thread is blocked.

x2 will wait for the lock to be released. Interestingly, the Operating System never thought that a thread could be executed in such behavior. Usually, the locks are valid among the threads. And once a thread tries to get the lock, the Operating System will block it until the lock is released.

In this specific case, the lock should be released by the thread itself! However, the thread is blocked by the OS, so the lock will never be released! The main reason is that the thread is preemptive scheduled, while the asynchronous functions are cooperate scheduled. The lock is invented for preemptive scheduling patterns.

So this story teaches us that we should be careful with Mutex in asynchronous programming. If you want to use std::Mutex in asynchronous programs, you should never let an await go inside the critical section.

© LICENSED UNDER CC BY-NC-SA 4.0