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 the mutex).
    如果 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). See recursive_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_lockstd::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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章