• 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();//获取idint 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::movet1.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::movet1.join();std::shared_future<string> future_con = future_.share(); //转移 :无法直接拷贝cout << future_con.get() << endl;
}int main()
{// Funture_Base_Use();Future_Progress_Use();
}

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

  1. java多线程互斥锁_浅谈Java多线程互斥锁

    为了解决竞争条件带来的问题,我们可以对资源上锁.多个线程共同读写的资源称为共享资源,也叫临界资源.涉及操作临界资源的代码区域称为临界区(Critical Section).同一时刻,只能有一个线程进入 ...

  2. golang:1.并发编程之互斥锁、读写锁详解

    本文转载自junjie,而后稍作修改. 一.互斥锁 互斥锁是传统的并发程序对共享资源进行访问控制的主要手段.它由标准库代码包sync中的Mutex结构体类型代表.sync.Mutex类型(确切地说,是 ...

  3. Go sync.Mutex互斥锁的学习

    1. 前言 1.1 基础回顾 原子操作:指那些不能够被打断的操作被称为原子操作,当有一个CPU在访问这块内容addr时,其他CPU就不能访问. CAS:比较及交换,其实也属于原子操作,但它是非阻塞的, ...

  4. SQLite3源码学习(18) 互斥锁

    互斥锁是为了保证在多线程时一些不可重入函数执行的串行化,有些函数如malloc等会操作一些共享数据,如果被重入了就会导致共享资源被破坏,从而出现逻辑错误,所以如果有多个线程对共享资源的访问就要加互斥锁 ...

  5. 互斥锁(排它锁、独占锁、写锁、X锁)和共享锁(读锁、S锁) 自旋锁

    共享锁(S锁):如果事务T对数据A加上共享锁后,则其他事务只能对A再加共享锁,不能加排他锁,直到已释放所有共享锁.获准共享锁的事务只能读数据,不能修改数据. 排他锁(X锁):如果事务T对数据A加上排他 ...

  6. Redis针对缓存击穿的解决方法-互斥锁

    参考至:Java岗大厂面试百日冲刺 - 日积月累,每日三题[Day2] -- Redis篇1_陈哈哈的菜园子-CSDN博客 缓存穿透:指缓存和数据库中都没有的数据,导致所有的请求都打到数据库上,然后数 ...

  7. 11.python并发入门(part3 多线程与互斥锁)

    一.锁的概念. 锁,通常被用来实现共享数据的访问,为每一个共享的数据,创建一个Lock对象(一把锁),当需要访问这个共享的资源时,可以调用acquire方法来获取一个锁的对象,当共享资源访问结束后,在 ...

  8. c++11 多线程编程(三)------ 竞争和互斥锁

    竞争条件 并发代码中最常见的错误之一就是竞争条件(race condition).而其中最常见的就是数据竞争(data race),从整体上来看,所有线程之间共享数据的问题,都是修改数据导致的,如果所 ...

  9. Python 多线程总结(2)— 线程锁、线程池、线程数量、互斥锁、死锁、线程同步

    主要介绍使用 threading 模块创建线程的 3 种方式,分别为: 创建 Thread 实例函数 创建 Thread 实例可调用的类对象 使用 Thread 派生子类的方式 多线程是提高效率的一种 ...

最新文章

  1. Mozilla宣布年底前放弃支持Persona登录服务
  2. linux高级编程补充知识
  3. java学习(65):类访问static修饰的内部类
  4. PJSIP学习笔记——PJSUA层发起呼叫的主要流程
  5. LeetCode 55. 跳跃游戏(贪心)
  6. 怎么创建自己的oracle,oracle 创建自己的wm_concat
  7. [转载] Python Dictionary用法小结
  8. python---保留两位小数
  9. python单位转换编程_[转]Python编程FAQ
  10. lae界面开发工具入门之介绍三--布局篇
  11. 众智动力java_Java泛型简明教程
  12. c++ 求点到直线的距离
  13. 学习C语言——字母金字塔
  14. 金山打字通计算机英语,金山打字通英文版
  15. 40行Python代码利用DOI下载英文论文(2022.3.7)
  16. 数据结构实践项目-------停车场管理系统
  17. 微信QQ邮箱插件,附件Excel 无法打开,或者打开乱码问题
  18. 系列微课|《Python程序设计(第3版)》第4章
  19. matlab cdfx,在 Simulink 数据字典中使用 ASAM CDFX 数据
  20. ES6新增——反撇号(`)基础知识

热门文章

  1. dedecms m view.php,dedecms在php7下的使用方法 织梦dedecsm后台一片空白的解决方法
  2. 动态规划解题一般思路
  3. servlet里面转发与重定向
  4. poj 1723 中位数
  5. 基础数据类型,注释,变量
  6. Spring Boot动态修改日志级别
  7. net core 小坑杂记之配置文件读取(不定期更新)
  8. 【吴恩达机器学习】学习笔记——1.5无监督学习
  9. Shell基础(一):Shell基础应用、简单Shell脚本的设计、使用Shell变量、变量的扩展应用...
  10. Mongodb05 - 数据操作(删除、游标)