首页 > 编程语言 >C++多线程同步和加锁的方式

C++多线程同步和加锁的方式

时间:2024-10-23 14:48:06浏览次数:7  
标签:std 多线程 lock C++ 互斥 加锁 线程 include

多线程同步和加锁的方式

1. 互斥锁(Mutex)

互斥锁是一种常见的线程同步机制,用于保护共享资源,确保同一时间只有一个线程可以 访问该资源。C++标准库提供了std::mutex类来实现互斥锁。
std::mutex的lock()成员函数获取锁,使用完毕后调用unlock()释放锁。推荐使用std::lock_guard或std::unique_lock等封装类,他们可以在构造时自动加锁,在析构式自动解锁,从而简化代码并减少死锁风险。

#include <mutex> 
#include <thread>
 std::mutex mtx; 
void threadFunction() 
{ 
	std::lock_guard<std::mutex> lock(mtx); // 自动加锁 
	// 临界区代码 
} 
int main() 
{
	std::thread t1(threadFunction); 
	std::thread t2(threadFunction);
    t1.join(); 
	t2.join(); 
	return 0; 
}

2. 递归锁

递归锁是互斥锁的一种特殊形式,允许同一线程多次获得锁而不会导致死锁,C++标准提供了std::recursive_mutex类来实现递归锁。支持同一现成多次调用lock()。

#include <mutex>
#include <thread>
 std::recursive_mutex rmtx;
 void recursiveFunction() 
{ 
	std::lock_guard<std::recursive_mutex> lock(rmtx); // 递归调用或再次加锁
} 
int main()
{ 
	// ...(与互斥锁示例相同)
}

3. 条件变量(Condition Variable)

条件变量用于线程间的等待和唤醒操作,通常与互斥锁一起使用,C++标准库提供了std::condition_variable和std::condition_variable_any类来实现条件变量。
使用方式:线程在等待某个条件成立时,会先加锁互斥锁,然后调用条件变量的wait()函数进入等待状态并释放锁。当条件成立时,另一个线程会调用notify_one()或notify_all()来唤醒一个或所有等待的线程。

#include <condition_variable>
#include <mutex> 
#include <thread> 
std::mutex mtx; 
std::condition_variable cv; 
bool ready = false; 
void print_id(int id)
{
 	std::unique_lock<std::mutex> lck(mtx); 
	while (!ready) cv.wait(lck); // ... 当ready为true时,执行临界区代码
 } 
void go() 
{ 
	std::unique_lock<std::mutex> lck(mtx); 
	ready = true; cv.notify_all(); // 唤醒所有等待的线程 
} 
int main() 
{ 
	std::thread threads[10]; // 创建线程... 
	go(); 
	// 设置ready为true并唤醒所有线程 
	// 等待线程结束...
}

4. 原子操作(Atomic Operation)

原子操作可以保证操作的不可分割性,即操作在执行过程中不会被其他线程打断。C++标准库提供了std::atomic模板类来实现原子操作。
使用方式:直接使用std::atomic模板类封装的变量进行操作,这些操作会自动地成为原子操作。

#include <atomic>
#include <thread> 
std::atomic<int> count(0); 
void increment()
{
 	++count; // 原子操作 
} 
int main() 
{ 
	std::thread t1(increment); 
	std::thread t2(increment); 
	t1.join(); 
	t2.join(); // 此时count的值至少为2
 }

5. 信号量(Semaphore)

信号量用于控制多个线程对共享资源的访问顺序和数量。C++20标准库引入了std::semaphore类来实现信号量。
使用方式:通过std::semaphore的acquire()和release()成员函数来控制资源的访问。

#include <semaphore>
#include <thread> 
std::semaphore sem(2); // 允许两个线程同时访问 
void task() 
{ 
	sem.acquire(); // 等待信号量 
	// 访问共享资源 
	sem.release(); // 释放信号量 
} 
int main()
{ 
	std::thread threads[5]; // 创建并启动线程... 
	// 等待线程结束... 
}

标签:std,多线程,lock,C++,互斥,加锁,线程,include
From: https://blog.csdn.net/qq_38556796/article/details/143183917

相关文章

  • C++实现stack功能
    C++代码实现stack功能,具体代码如下:#include"stdafx.h"#include<iostream>#include<vector>#include<stdexcept>//forstd::out_of_rangetemplate<typenameT>classStack{private: std::vector<T>elements;//底层容器,用于存......
  • C++试题带答案
    阅读以下程序,回答问题1.试写出下列程序的输出结果与功能。 输出:2   sunny  24功能:求所有同学中年龄最大的同学2.试写出下列程序中函数fun()的功能及程序的输出结果。 函数fun()的功能:实现整数m的逆向输出程序的输出结果:543213.简述String类中Setc、Getc和Append三......
  • c++计时器
    c++计时器鼠标版#include<bits/stdc++.h>#include<windows.h>#definekd(vk)(GetAsyncKeyState(vk)&0x8000?1:0)usingnamespacestd;#defineSHAKE30voidShakeWindow(){ RECTrect; HWNDhwnd=GetConsoleWindow(); GetWindowRect(hwnd,&rect);......
  • 【unity】 Loom实现多线程
    ​通常情况下,unity中在子线程中改变变量的值,但是子线程尚未结束时,主线程无法使用该变量。因此使用Loom作为中介,子线程调用并传值给Loom,Loom调用主线程的API。实现步骤创建Loom空物体,并挂载Loom脚本//Loom.csusingSystem;usingSystem.Collections;usingSystem.Collectio......
  • selenium单例模式下 docker-chrome 多线程并发代码
    最近需要写爬虫,在解决docker-standalone-chrome发现只能有一个chrome被执行。所以写了这个多线程并发控制类来管理。当模板记录下。#!/usr/bin/envpython3importthreadingimporttracebackfromloguruimportloggerfromseleniumimportwebdriverfromselenium.comm......
  • C++刷题tricks整理
    是自己做题中整理的常用C++操作,此为存档。STL容器容器适配器,STL里面的vector/array/deque/set/map/unordered_set可以直接使用==比较是否相等:vector<int>a;deque<int>a;map<int,string>a;unordered_map<int,string>a;set<int>a;unordered_set<int>a;forward_lis......
  • 马拉车算法(C/C++)
    #1024程序员节|征文#马拉车算法(Manacher'sAlgorithm)是一种用于在字符串中查找最长回文子串的线性时间复杂度算法。该算法由UdiManacher在1980年代提出,因此得名。它的核心思想是利用已知的回文信息来减少不必要的比较,从而提高效率。算法步骤预处理字符串:为了处理奇数......
  • C++入门Day5 ~ 6:简单变量 & 数据类型 part 1 <8000字长文带你初步理解数据类型>
    这是我在学习中的一个小问题,希望对你也有所帮助:        问:数据类型和简单变量属于oop的基本概念吗?        答:不是!数据类型和简单变量本身并不属于面向对象编程(OOP)的基本概念,但它们是编程中的基础概念,面向对象编程会基于这些基础概念来构建更复杂的结构。......
  • C++基础——寻找水仙花数
    C++基础——寻找水仙花数一、水仙花数1.什么是水仙花数2.编译思路二、头文件三、主文件四、整体代码五、运行结果一、水仙花数1.什么是水仙花数原理:我们先理解什么是水仙花数(NarcissisticNumber),所谓的水仙花数是指一个整数的各位数字的立方和等于它本身。例如153......
  • 【C++】踏上C++学习之旅(三):“我“ 与 “引用“ 的浪漫邂逅
    文章目录前言1."引用"的概念1.1"引用"的语法2."引用"的特性3."引用"的使用场景3.1"引用"做参数3.2"引用"做返回值3.2.1"引用"做返回值时需要注意的点4.常引用5."引用"在底层的实现6."引用"和"指针"的不同点(面试常考)前言本文会着重的讲解&q......