C++ 11互斥锁的应用(针对于多线程的情况)

  • C++ 11 线程锁:

  • 一、mutex

    使用方法:

    • 1.mutex的lock和unlock(最基本的操作)

      mutex g_mutex;
      g_mutex.lock();
      cout << "test" << endl;
      g_mutex.unlock();
      

      2.try_lock_for:尝试上锁,如果前面已经上锁了 则返回false,否则返回true

      用法:

      void run500ms(std::timed_mutex &mutex) {
      	auto _500ms = std::chrono::milliseconds(0);
      	if (mutex.try_lock_for(_500ms)) // 如果前面已经上锁了 那就返回false 否则返回true
      	{
      		std::cout << "获得了锁" << std::endl;
      	}
      	else {
      		std::cout << "未获得锁" << std::endl;
      	}
      }
      
      	mutex.lock();
      	std::thread thread(run500ms, std::ref(mutex));
      	thread.join();
      	mutex.unlock();
      

    二、lock_guard

    • lock_guard 不会产生死锁,但是管理不了Mutex的生命周期,最好的方式是将mutex 设置为全局变量

    • 构造函数中加锁,析构函数中解锁

    • 代码

      	try {
      		std::lock_guard<std::mutex> _guard(g_mutex); //  构造函数中加锁 析构函数中解锁
      		if (g_mutex.try_lock())
      		{
      			cout << "加锁ok" << endl;
      		}
      		else
      		{
      			cout <<"加锁失败"  << endl;
      		}
      		throw std::logic_error("qqlogic error");
      	}
      	catch (std::exception &ex) {
      		std::cerr << "[caught] ee" << ex.what() << std::endl;
      	}
      

    三、unique_lock

    扫描二维码关注公众号,回复: 10014368 查看本文章
    • 可以接管mutex生命周期
mutex g_mutt;
//g_mutt.lock();
  	std::unique_lock<std::mutex> unique_guard(g_mutt, std::try_to_lock);
  • 其中第二个参数可选为:std::adopt_lock 这说明之前已经加过锁了,
  • std::try_to_lock: 说明尝试加锁
  • release方法 类似于转移所有权

实例代码

void test_Unique_Lock(std::unique_lock<std::mutex> & mutex_)
{
	for (int i = 0; i < 10; i++)
	{
		cout << "1222" << endl;
	}
}

void Thread_Unique_Lock_Use()
{
	mutex g_mutt;
	//g_mutt.lock();
	std::unique_lock<std::mutex> unique_guard(g_mutt, std::try_to_lock); // std::adopt_lock 说明之前已经上锁了
	std::thread t1(test_Unique_Lock,std::ref(unique_guard));
	std::mutex* gss_mutex = unique_guard.release(); //返回 相当于转移
	gss_mutex->unlock();
	t1.join();
}
  • 完整实验代码

// ThreadsDemo.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
// C++ 11 多线程


#include "pch.h"
#include <iostream>
#include <Windows.h>
#include <thread>
#include <string.h>
#include <mutex>
#include <chrono>
using namespace std::chrono;
using namespace std;



void hello()
{
	std::mutex g_mutex;
	g_mutex.lock();
	for (int i = 0; i < 10; i++)
	{
		cout << "Hello World!" << endl;
	}
	g_mutex.unlock();
}

void run500ms(std::timed_mutex &mutex) {
	auto _500ms = std::chrono::milliseconds(0);
	if (mutex.try_lock_for(_500ms)) // 如果前面已经上锁了 那就返回false 否则返回true
	{
		std::cout << "获得了锁" << std::endl;
	}
	else {
		std::cout << "未获得锁" << std::endl;
	}
}

class A {
public: 
	A() {
		cout << "A Init" << endl;
	}
	~A() {
		cout << "A Destroy" << endl;
	}
	void ShowA() {
		std::mutex g_mutex;
		g_mutex.lock();
		for (size_t i = 0; i < 13; i++)
		{
			cout << "Show A Value" << endl;
		}
		g_mutex.unlock();
	}
}
;

void CarryParams(std::string params_,int f_)
{
	cout << params_.c_str() << endl;
	cout << f_ << endl;
}

void Thread_Base_Use()
{
	std::thread t(hello);
	//t.join(); // 主线程需要等待子线程结束之后 才能继续运行
	t.detach(); // 这种情况的话 主线程无需等待子线程结束

	std::string m1 = "sqd";
	std::thread t1(CarryParams, std::ref(m1),1133); //带参数 //std::ref 引用的方式
	std::thread t2 = std::move(t1); //可以转移所有权
	t2.join();
	std::thread::id thread_id = t2.get_id();//获取id
	int thread_num = thread::hardware_concurrency();
	cout << "输出输了" << thread_num;
	std::cout << "ceshi ";
}


void Thread_Class_Use(){
	A a_;
	std::thread t1(&A::ShowA,&a_); // 作为成员函数时,必须传递类指针
	t1.join();
	return;
}

void Thread_Mutex_Use()
{
	std::timed_mutex mutex;

	mutex.lock();
	std::thread thread(run500ms, std::ref(mutex));
	thread.join();
	mutex.unlock();

}

void safe_thread() {
	std::mutex g_mutex;
	try {
		std::lock_guard<std::mutex> _guard(g_mutex); //  构造函数中加锁 析构函数中解锁
		if (g_mutex.try_lock())
		{
			cout << "加锁ok" << endl;
		}
		else
		{
			cout <<"加锁失败"  << endl;
		}
		throw std::logic_error("qqlogic error");
	}
	catch (std::exception &ex) {
		std::cerr << "[caught] ee" << ex.what() << std::endl;
	}
}

void test_Unique_Lock(std::unique_lock<std::mutex> & mutex_)
{
	for (int i = 0; i < 10; i++)
	{
		cout << "1222" << endl;
	}
}

//
void Thread_Lock_Guard_Use()
{
	std::mutex g_mutex;
	safe_thread();
	g_mutex.lock();
	cout << "上锁成功" << endl;
	g_mutex.unlock();//解锁
}

void Thread_Unique_Lock_Use()
{
	mutex g_mutt;
	//g_mutt.lock();
	std::unique_lock<std::mutex> unique_guard(g_mutt, std::try_to_lock); // std::adopt_lock 说明之前已经上锁了
	std::thread t1(test_Unique_Lock,std::ref(unique_guard));
	std::mutex* gss_mutex = unique_guard.release(); //返回 相当于转移
	gss_mutex->unlock();
	t1.join();
}

int main()
{
	//Thread_Lock_Guard_Use();
	Thread_Unique_Lock_Use();
}


  • 条件变量
// ThreadCondition.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include "pch.h"
#include <iostream>
#include <condition_variable>
#include <mutex>
#include <thread>

using namespace std;
std::condition_variable cv;

void App_WakeUp(std::unique_lock<std::mutex> & lock_)
{
	cv.wait(lock_);
	cout << "Init Test" << endl;
	cout << "wait wait wait" << endl;
	lock_.unlock(); // 之后需要解锁 不然会报错 : 需要在同一线程中进行加锁和解锁操作
}

void Thread_Condition_Use()
{
	std::mutex mutex;


	// 条件变量与临界区有关,用来获取和释放一个锁,因此通常会和mutex联用。
	std::unique_lock<std::mutex> lock_(mutex);
	// 此处会释放lock,然后在cv上等待,直到其它线程通过cv.notify_xxx来唤醒当前线程,cv被唤醒后会再次对lock进行上锁,然后wait函数才会返回。
	// wait返回后可以安全的使用mutex保护的临界区内的数据。此时mutex仍为上锁状态
	std::thread t12(App_WakeUp,std::ref(lock_));
	cout << "Init DEMSDADAASACCCCAO    " << endl;
	cv.notify_all(); // 其中notify_one 和 notify_all 差不多
	t12.join();
}


int main()
{
	Thread_Condition_Use();
}

  • future以及package_task的基本使用
// AsyncThreads.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
// 多线程Promise 使用

#include "pch.h"
#include <iostream>

#include <thread>
#include <string>
#include <future>
#include <chrono>
using namespace std::chrono;
using namespace std;

void testFuture(std::future<std::string>& future_)
{
	cout << future_.get() << endl;
}

void Funture_Base_Use(){
	std::promise<std::string> promise_;
	std::future<std::string> future_ = promise_.get_future();
	std::thread thread_(testFuture,std::ref(future_));
    promise_.set_value("test future receiver");
	thread_.join();
}

std::string  test_str_(string str1,string str2)
{
	return str1.append(str2);
}

void Package_Base_Use()
{
	/*
	*使用方式:
	 template <class R, class... ArgTypes>
     class packaged_task<R(ArgTypes...)>
	*
	*/
	std::packaged_task<std::string(string, string)> task_(test_str_); // 第一个参数 返回值,
	std::future<string> future_ = task_.get_future();
	std::thread t1(std::move(task_),"ssa","scc"); // 需要使用std::move
	t1.join();
	cout << future_.get() << endl;
}

// Future 进阶使用
void Future_Progress_Use()
{
	std::packaged_task<std::string(string, string)> task_(test_str_); // 第一个参数 返回值,
	std::future<string> future_ = task_.get_future();
	std::thread t1(std::move(task_), "ssa", "scc"); // 需要使用std::move
	t1.join();
	std::shared_future<string> future_con = future_.share(); //转移 :无法直接拷贝
	cout << future_con.get() << endl;
}

int main()
{
	//	Funture_Base_Use();
	Future_Progress_Use();
}
发布了382 篇原创文章 · 获赞 122 · 访问量 40万+

猜你喜欢

转载自blog.csdn.net/Giser_D/article/details/104428264