std::mutex::lock
std::mutex::lock
Defined in header <mutex>
- 定义于头文件 <mutex>
public member function - 公开成员函数
锁定互斥,若互斥不可用则阻塞。
mutex:n. 互斥,互斥元,互斥体,互斥量
synchronization [ˌsɪŋkrənaɪˈzeɪʃn]:n. 同步,同时性
primitive [ˈprɪmətɪv]:adj. 原始的,远古的,简单的,粗糙的 n. 原始人
simultaneously [ˌsɪmlˈteɪniəsli]:adv. 同时地
exclusive [ɪkˈskluːsɪv]:adj. 独有的,排外的,专一的 n. 独家新闻,独家经营的项目,排外者
semantics [sɪˈmæntɪks]:n. 语义学,语义论
recursive [rɪˈkɜːsɪv]:adj. 递归的,循环的
1. std::mutex::lock
void lock();
- since C++11
Locks the mutex
. If another thread has already locked the mutex
, a call to lock
will block execution until the lock is acquired.
锁定 mutex
。若另一线程已锁定 mutex
,则到 lock
的调用将阻塞执行,直至获得锁。
If lock
is called by a thread that already owns the mutex
, the behavior is undefined: for example, the program may deadlock. An implementation that can detect the invalid usage is encouraged to throw a std::system_error
with error condition resource_deadlock_would_occur
instead of deadlocking.
若 lock
为已占有 mutex
的线程调用,则行为未定义:例如,程序可能死锁。鼓励能检测非法使用的实现抛出以 resource_deadlock_would_occur
为错误条件的 std::system_error
,而不是死锁。
Prior unlock()
operations on the same mutex
synchronize-with (as defined in std::memory_order
) this operation.
同一 mutex
上先前的 unlock()
操作同步于 (定义于 std::memory_order
) 此操作。
Lock mutex
- 锁定 mutex
The calling thread locks the mutex
, blocking if necessary:
调用线程锁定 mutex
,必要时阻塞:
-
If the
mutex
isn’t currently locked by any thread, the calling thread locks it (from this point, and until its member unlock is called, the thread owns themutex
).
如果mutex
当前未被任何线程锁定,则调用线程将其锁定 (从这此时开始,直到调用其成员 unlock,该线程拥有mutex
)。 -
If the
mutex
is currently locked by another thread, execution of the calling thread is blocked until unlocked by the other thread (other non-locked threads continue their execution).
如果mutex
当前被另一个线程锁定,则调用线程的执行将被阻止,直到被另一个线程解锁 (其他非锁定线程继续执行)。 -
If the
mutex
is currently locked by the same thread calling this function, it produces a deadlock (with undefined behavior). Seerecursive_mutex
for a mutex type that allows multiple locks from the same thread.
如果mutex
当前被调用此函数的同一线程锁定,则会产生死锁 (行为未定义)。请参阅recursive_mutex
以获取mutex
类型,该类型允许来自同一线程的多个锁。
All lock
and unlock
operations on the mutex
follow a single total order, with all visible effects synchronized between the lock operations and previous unlock operations on the same object.
互斥锁上的所有 lock
and unlock
操作都遵循一个总顺序,所有可见效果在同一对象上的锁定操作和先前的解锁操作之间同步。
The non-member function lock
allows to lock more than one mutex
object simultaneously, avoiding the potential deadlocks that can happen when multiple threads lock/unlock
individual mutex
objects in different orders.
非成员函数 lock
允许同时锁定多个 mutex
对象,避免了当多个线程以不同顺序 lock/unlock
单个 mutex
对象时可能发生的死锁。
Note that the order in which different concurrent locks are scheduled to return is unspecified, and not necessarily related to the order in which they are locked (depending on the system and library implementation).
请注意,被调度的不同并发锁返回的顺序是不确定的,并且不一定与它们被锁定的顺序有关 (取决于系统和库的实现)。
intermingle [ˌɪntəˈmɪŋɡl]:vt. 使混合,使搀和 vi. 混合,掺杂
Throws std::system_error
when errors occur, including errors from the underlying operating system that would prevent lock from meeting its specifications. The mutex
is not locked in the case of any exception being thrown.
错误发生时抛出 std::system_error
,包括来自底层操作系统的错误,这些错误会导致锁无法满足其规范。在抛出任何异常的情况下,不锁定 mutex
。
lock()
is usually not called directly: std::unique_lock
and std::lock_guard
are used to manage exclusive locking.
通常不直接调用 lock()
:用 std::unique_lock
与 std::lock_guard
管理排他性锁定。
2. Parameters
none
3. Return value
none
4. Example - 示例
4. 1 std::mutex::lock/unlock
//============================================================================
// Name : std::mutex::lock/unlock
// Author : Yongqiang Cheng
// Version : Version 1.0.0
// Copyright : Copyright (c) 2019 Yongqiang Cheng
// Description : Hello World in C++, Ansi-style
//============================================================================
#include <iostream> // std::cout
#include <thread> // std::thread
#include <mutex> // std::mutex
std::mutex mtx; // mutex for critical section
void print_thread_id(int id)
{
// critical section (exclusive access to std::cout signaled by locking mtx):
mtx.lock();
std::cout << "thread #" << id << "-->";
std::cout << "thread #" << id << '\n';
mtx.unlock();
}
int main()
{
std::thread threads[10];
// spawn 10 threads:
for (int i = 0; i < 10; ++i)
{
threads[i] = std::thread(print_thread_id, i + 1);
}
for (auto& th : threads)
{
th.join();
}
return 0;
}
Possible output (order of lines may vary, but they are never intermingled):
可能的输出 (行的顺序可能会有所不同,但是它们永远不会混合在一起):
thread #1-->thread #1
thread #7-->thread #7
thread #2-->thread #2
thread #9-->thread #9
thread #4-->thread #4
thread #6-->thread #6
thread #5-->thread #5
thread #8-->thread #8
thread #3-->thread #3
thread #10-->thread #10
4.2 std::mutex::lock
//============================================================================
// Name : std::mutex::lock
// Author : Yongqiang Cheng
// Version : Version 1.0.0
// Copyright : Copyright (c) 2019 Yongqiang Cheng
// Description : Hello World in C++, Ansi-style
//============================================================================
#include <iostream>
#include <chrono>
#include <thread>
#include <mutex>
int g_num = 0; // protected by g_num_mutex
std::mutex g_num_mutex;
void slow_increment(int id)
{
for (int i = 0; i < 5; ++i)
{
g_num_mutex.lock();
++g_num;
std::cout << id << " => " << g_num << '\n';
g_num_mutex.unlock();
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
int main()
{
std::thread t1(slow_increment, 0);
std::thread t2(slow_increment, 1);
t1.join();
t2.join();
return 0;
}
1 => 1
0 => 2
1 => 3
0 => 4
1 => 5
0 => 6
1 => 7
0 => 8
1 => 9
0 => 10
5. Data races - 数据竞争
The mutex object is modified as an atomic operation (causing no data races).
互斥对象被修改为原子操作 (不引起数据竞争)。
6. Exception safety - 异常安全性
Basic guarantee: if an exception is thrown by this member function, the mutex
object is left in a valid state. Further, a lock is never acquired by the thread that made the throwing call.
基本保证:如果此成员函数引发异常,则 mutex
对象将保持有效状态。此外,进行抛出调用的线程永远不会获得锁定。
If the mutex
is already locked by the current thread, calling this function causes a deadlock (undefined behavior): on certain library implementations, this causes the function to fail.
如果 mutex
已被当前线程锁定,则调用此函数将导致死锁 (未定义行为):在某些库实现中,这将导致函数失败。
If the call fails, a system_error
exception is thrown:
如果调用失败,将抛出 system_error
异常:
exception type | error condition | description |
---|---|---|
system_error | errc::resource_deadlock_would_occur | A deadlock was detected (implementations may detect certain cases of deadlock). - 检测到死锁 (实现可能检测到某些死锁情况)。 |
system_error | errc::operation_not_permitted | The thread does not have privileges to perform the operation. - 该线程没有执行该操作的权限。 |
system_error | errc::device_or_resource_busy | The native handle type manipulated is already locked. - 操作的本机句柄类型已被锁定。 |
Depending on the library implementation, this member function may also throw exceptions to report other situations.
根据库的实现,此成员函数还可能引发异常以报告其他情况。
Reference
http://www.cplusplus.com/reference/mutex/mutex/lock/
https://en.cppreference.com/w/cpp/thread/mutex/lock