为什么我要在一个功能中锁定两个互斥锁-延迟锁定也要锁定吗? [英] Why would I want to lock two mutexes in one function - that too with deferred lock?

查看:142
本文介绍了为什么我要在一个功能中锁定两个互斥锁-延迟锁定也要锁定吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

https://en.cppreference.com/w/cpp/thread/lock_tag

void transfer(bank_account &from, bank_account &to, int amount)
{
    // lock both mutexes without deadlock
    std::lock(from.m, to.m);
    // make sure both already-locked mutexes are unlocked at the end of scope
    std::lock_guard<std::mutex> lock1(from.m, std::adopt_lock);
    std::lock_guard<std::mutex> lock2(to.m, std::adopt_lock);

// equivalent approach:
//    std::unique_lock<std::mutex> lock1(from.m, std::defer_lock);
//    std::unique_lock<std::mutex> lock2(to.m, std::defer_lock);
//    std::lock(lock1, lock2);

    from.balance -= amount;
    to.balance += amount;
}

一次锁定两个互斥锁会得到什么?
他们在这里延迟锁定获得了什么?

What do they gain by locking two mutexes at once?
What have they gained by defered lock here?

请解释他们做出该决定的原因.

Please explain the reason behind that decision of theirs.

推荐答案

Richard Hodges answer

一次锁定两个互斥锁会得到什么?

What do they gain by locking two mutexes at once?

Richard已经很好地解释了,只是更加明确了一点:我们以这种方式避免了死锁(实现了std::lock使得不会发生死锁).

Richard explained nicely already, just a little bit more explicit: we avoid dead-lock this way (std::lock is implemented such that dead-lock won't occur).

通过这里的延迟锁定,他们获得了什么?

What have they gained by deferred lock here?

推迟锁定将导致无法立即获取它.这很重要,因为如果他们 did 这样做,他们只会在没有任何防止死锁的情况下做到这一点(随后的std::lock随后会实现).

Deferring the lock results in not acquiring it immediately. That's important because if they did so, they would just do it without any protection against dead-lock (which the subsequent std::lock then achieves).

关于避免死锁(请参阅 std :: lock ):

About dead lock avoidance (see std::lock):

使用避免死锁算法来避免死锁来锁定给定的Lockable对象lock1,lock2,...,lockn.

Locks the given Lockable objects lock1, lock2, ..., lockn using a deadlock avoidance algorithm to avoid deadlock.

对象通过一系列未指定的锁定,try_lock和unlock调用来锁定. [...]

The objects are locked by an unspecified series of calls to lock, try_lock, and unlock. [...]

侧面说明:避免死锁的另一种更简单的算法是始终使用e锁定银行帐户. G.请先输入较低的帐号(AN).如果一个线程正在等待较高AN的锁,则持有它的另一个线程可能已经获取了两个锁,或者正在等待第二个锁.不能成为第一个线程之一,因为它必须具有更高的AN.

Side note: another, much simpler algorithm avoiding dead locks is always locking the bank account with e. g. lower account number (AN) first. If a thread is waiting for the lock of higher AN, then the other thread holding it either already has both of the locks acquired or is waiting for the second – which cannot be the one of the first thread as it must have a yet higher AN.

这对于任意数量的线程来说并没有太大变化,任何持有较低锁的线程都在等待较高的锁(如果也持有).如果在A等待B持有的第二把锁的情况下绘制从A到B的有向图,则将得到一个(多)树结构,但是您将永远不会有圆形的子结构(这表示死了)锁定).

This does not change much for arbitrary number of threads, any thread holding a lower lock is waiting for a higher one, if hold as well. If you draw a directed graph with edges from A to B if A is waiting for second lock that B holds, you'll get a (multi-) tree structure, but you won't ever have circular substructures (which would indicate a dead lock).

这篇关于为什么我要在一个功能中锁定两个互斥锁-延迟锁定也要锁定吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆