c++11总结19——std::mutex

1. 头文件

#include

2. 分类

  • std::mutex——最基本的mutex类
  • std::recursive_mutex——递归mutex类
  • std::time_mutex——定时mutex类
  • std::recursive_timed_mutex——定时递归mutex类

3. std::mutex

3.1 概念

std::mutex 是C++11 中最基本的互斥量,std::mutex 对象提供了独占所有权的特性——即非递归锁,而 std::recursive_lock 则可以递归地对互斥量对象上锁。

3.2 成员函数

1)构造函数:不允许拷贝构造,也不允许 move 拷贝,最初产生的 mutex 对象是处于 unlocked 状态的;

2)lock():调用线程将锁住该互斥量;

线程调用该函数会发生下面 3 种情况:

  • 如果该互斥量当前没有被锁住,则调用线程将该互斥量锁住,直到调用 unlock之前,该线程一直拥有该锁;
  • 如果当前互斥量被其他线程锁住,则当前的调用线程被阻塞住
  • 如果当前互斥量被当前调用线程锁住,则会产生死锁(deadlock);

3)unlock():解锁,释放对互斥量的所有权;

4)try_lock():尝试锁住互斥量,如果互斥量被其他线程占有,则当前线程也不会被阻塞;

线程调用该函数会出现下面 3 种情况:

  • 如果当前互斥量没有被其他线程占有,则该线程锁住互斥量,直到该线程调用 unlock 释放互斥量;
  • 如果当前互斥量被其他线程锁住,则当前调用线程返回 false,而并不会被阻塞掉
  • 如果当前互斥量被当前调用线程锁住,则会产生死锁;

3.3 示例

#include 
#include 
#include 
using namespace std;

std::mutex mtx;

void PrintLock(int n, char c)
{
	mtx.lock();
	
	for(int i = 0; i < n; i++) {
		cout << c;
	}
	cout<<'\n';

	mtx.unlock();
}

int main()
{
	std::thread t1(PrintLock, 50, '*');
	std::thread t2(PrintLock, 50, '$');

	t1.join();
	t2.join();

	return 0;
}

编译运行:

[root@192 mutex]# g++ -lpthread  -o mutex mutex.cpp 
[root@192 mutex]# ./mutex
**************************************************
$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
[root@192 mutex]# 

4. std::recursive_mutex

std::recursive_mutex 允许同一个线程对互斥量多次上锁(即递归上锁)来获得对互斥量对象的多层所有权,std::recursive_mutex 释放互斥量时需要调用与该锁层次深度相同次数的 unlock()。

注意:

lock()和unlock()的调用次数应该相同。

5. std::time_mutex

5.1 成员函数

1)try_lock_for():接受一个时间范围,表示在这一段时间范围之内线程如果没有获得锁则被阻塞住(与 std::mutex 的 try_lock() 不同,try_lock 如果被调用时没有获得锁则直接返回 false),如果在此期间其他线程释放了锁,则该线程可以获得对互斥量的锁,如果超时(即在指定时间内还是没有获得锁),则返回 false。

2)try_lock_until():接受一个时间点作为参数,在指定时间点未到来之前线程如果没有获得锁则被阻塞住,如果在此期间其他线程释放了锁,则该线程可以获得对互斥量的锁,如果超时(即在指定时间内还是没有获得锁),则返回 false。

5.2 示例

#include        
#include          
#include        
#include          
using namespace std;

std::timed_mutex mtx;

void fireworks () {
  // waiting to get a lock: each thread prints "-" every 200ms:
  while (!mtx.try_lock_for(std::chrono::milliseconds(200))) {
    cout << "-";
  }
  // got a lock! - wait for 1s, then this thread prints "*"
  std::this_thread::sleep_for(std::chrono::milliseconds(1000));
  cout << "*\n";
  mtx.unlock();
}

int main ()
{
  std::thread threads[10];
  for (int i=0; i<10; ++i)
    threads[i] = std::thread(fireworks);

  for (auto& th : threads) th.join();

  return 0;
}

编译运行:

[root@192 mutex]# g++ -lpthread -o try_lock_for try_lock_for.cpp 
[root@192 mutex]# ./try_lock_for
------------------------------------*
----------------------------------------*
-----------------------------------*
------------------------------*
-------------------------*
--------------------*
---------------*
----------*
-----*
*
[root@192 mutex]# 

6. std::lock_guard

#include     
#include         
#include          
#include      
using namespace std;

std::mutex mtx;

void print_even (int x) {
  if (x%2==0) std::cout << x << " is even\n";
  else throw (std::logic_error("not even"));
}

void print_thread_id (int id) {
  try {
    std::lock_guard lck (mtx);
    print_even(id);
  }
  catch (std::logic_error&) {
    std::cout << "[exception caught]\n";
  }
}

int main ()
{
  std::thread threads[10];
  for (int i=0; i<10; ++i)
    threads[i] = std::thread(print_thread_id,i+1);

  for (auto& th : threads) th.join();

  return 0;
}

编译运行:

[root@192 mutex]# g++ -lpthread -o lock_guard lock_guard.cpp 
[root@192 mutex]# ./lock_guard
2 is even
[exception caught]
[exception caught]
4 is even
[exception caught]
6 is even
[exception caught]
8 is even
[exception caught]
10 is even
[root@192 mutex]# 

7. std::unique_lock

#include        
#include          
#include           

std::mutex mtx;        

void print_block (int n, char c) {
  std::unique_lock lck (mtx);
  for (int i=0; i

编译运行:

[root@192 mutex]# g++ -lpthread -o unique_lock unique_lock.cpp 
[root@192 mutex]# ./unique_lock
**************************************************
$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$

你可能感兴趣的:(c++11/17,mutex)