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

推荐订阅源

TaoSecurity Blog
TaoSecurity Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
F
Fortinet All Blogs
Cisco Talos Blog
Cisco Talos Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
S
Secure Thoughts
美团技术团队
雷峰网
雷峰网
Hugging Face - Blog
Hugging Face - Blog
博客园_首页
C
CXSECURITY Database RSS Feed - CXSecurity.com
Engineering at Meta
Engineering at Meta
人人都是产品经理
人人都是产品经理
月光博客
月光博客
T
Tor Project blog
P
Privacy & Cybersecurity Law Blog
Recorded Future
Recorded Future
I
Intezer
博客园 - 【当耐特】
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
GbyAI
GbyAI
罗磊的独立博客
V
V2EX
Google DeepMind News
Google DeepMind News
D
DataBreaches.Net
Last Week in AI
Last Week in AI
T
Tailwind CSS Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
A
About on SuperTechFans
Scott Helme
Scott Helme
Vercel News
Vercel News
Spread Privacy
Spread Privacy
T
Threat Research - Cisco Blogs
Recent Announcements
Recent Announcements
Hacker News: Ask HN
Hacker News: Ask HN
C
CERT Recently Published Vulnerability Notes
G
Google Developers Blog
B
Blog
博客园 - 叶小钗
WordPress大学
WordPress大学
博客园 - 聂微东
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Jina AI
Jina AI
IT之家
IT之家
C
Cybersecurity and Infrastructure Security Agency CISA
P
Palo Alto Networks Blog
小众软件
小众软件
博客园 - Franky
Microsoft Azure Blog
Microsoft Azure Blog
AWS News Blog
AWS News Blog

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 Sakai and Local Folder Synchronization Building a Super Simple OpenJudge in Two Nights Setting Up Remote Backup for macOS Shell Script for Automatically Logging into SUSTech Campus Network Building a Movie Streaming System in the Dorm
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