- 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
- 可以接管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();
}