多线程高并发

不正常情况说明::

线程1执行第一行50移动到eax

然后切换线程2,线程2全部执行完成++为51;

切换线程1,执行eax++也就是50+1=51

join和detach区别:

#include <iostream>
#include <thread>
#include <windows.h>

void foo()
{
	std::cout << "Run New thread!\n";
	Sleep(2000);   		//需要头文件<windows.h>
}

int main()
{
	std::thread t(foo);

	if (t.joinable())
	{
		t.join();  		// 等待线程t执行完毕

		 //t.detach();  // 分离线程t与主线程
	}

	std::cout << "Run Main thread!\n";
	return 0;
}

join:先显示new,过两秒显示main

互斥锁mutex

#include <iostream>
#include <thread>
#include <mutex>

std::mutex mtx;
int num = 0;

void thread_function(int& n)
{
	for (int i = 0; i < 100; ++i)
	{
		mtx.lock();
		n++;
		mtx.unlock();
	}
}

int main()
{
	std::thread myThread[500];
	for (std::thread& a : myThread)
	{
		a = std::thread(thread_function, std::ref(num));
		a.join();
	}

	std::cout << "num = " << num << std::endl;
	std::cout << "Main thread exits!" << std::endl;
	return 0;
}

代码的目标是让多个线程(500个线程)同时对一个共享变量num进行递增操作

  • 使用 std::ref(num) 确保 num 是按引用传递给 thread_function 的,而不是传递一个副本。

lock_guard:

用于实现资源的自动加锁和解锁。它是基于RAII(资源获取即初始化)的设计理念,能够确保在作用域结束时自动释放锁资源,避免了手动管理锁的复杂性和可能出现的错误。

std::lock_guard的主要特点如下:

自动加锁: 在创建std::lock_guard对象时,会立即对指定的互斥量进行加锁操作。这样可以确保在进入作用域后,互斥量已经被锁定,避免了并发访问资源的竞争条件。
自动解锁:std::lock_guard对象在作用域结束时,会自动释放互斥量。无论作用域是通过正常的流程结束、异常抛出还是使用return语句提前返回,std::lock_guard都能保证互斥量被正确解锁,避免了资源泄漏和死锁的风险。
适用于局部锁定: 由于std::lock_guard是通过栈上的对象实现的,因此适用于在局部范围内锁定互斥量。当超出std::lock_guard对象的作用域时,互斥量会自动解锁,释放控制权。


使用std::lock_guard的一般步骤如下:

创建一个std::lock_guard对象,传入要加锁的互斥量作为参数。
执行需要加锁保护的代码块。
std::lock_guard对象的作用域结束时,自动调用析构函数解锁互斥量。

需要在自己需要的作用域加一个大括号,太麻烦了,引出unique lock

unique_lock

std::unique_lock是C++标准库中的一个模板类,用于实现更加灵活的互斥量的加锁和解锁操作。它提供了比std::lock_guard更多的功能和灵活性。

#include <iostream>
#include <thread>
#include <mutex>

std::mutex mtx;  // 互斥量

void thread_function()
{
    std::unique_lock<std::mutex> lock(mtx);  // 加锁互斥量
    std::cout << "Thread running" << std::endl;
    // 执行需要加锁保护的代码
    lock.unlock();  // 手动解锁互斥量
    // 执行不需要加锁保护的代码
    lock.lock();  // 再次加锁互斥量
    // 执行需要加锁保护的代码
}  
// unique_lock对象的析构函数自动解锁互斥量

int main()
{
    std::thread t1(thread_function);
    t1.join();
    std::cout << "Main thread exits!" << std::endl;
    return 0;
}

条件变量:
 

#include <iostream>
#include <thread>
#include <condition_variable>

std::mutex mtx;  // 互斥量
std::condition_variable cv;  // 条件变量
bool isReady = false;  // 条件

void thread_function()
{
    std::unique_lock<std::mutex> lock(mtx);
    while (!isReady) 
    {
        cv.wait(lock);  // 等待条件满足
    }
    std::cout << "Thread is notified" << std::endl;
}

int main()
{
    std::thread t(thread_function);

    // 模拟一段耗时操作
    std::this_thread::sleep_for(std::chrono::seconds(2));

    {
        std::lock_guard<std::mutex> lock(mtx);
        isReady = true;  // 设置条件为true
    }
    cv.notify_one();  // 通知等待的线程

    t.join();

    return 0;
}

创建了一个线程,该线程在等待状态下通过cv.wait(lock)等待条件满足。主线程经过一段时间后将条件设置为true,然后通过cv.notify_one()通知等待的线程。等待的线程被唤醒后输出一条消息。有wait就要有通知notify不然不会指执行

一样的

读写锁

#include <iostream>
#include <thread>
#include <vector>
#include <shared_mutex>

std::shared_mutex rw_mutex;  // 读写锁
int shared_data = 0;         // 共享数据

// 读操作
void read_data(int id) {
    std::shared_lock<std::shared_mutex> lock(rw_mutex);  // 获取共享锁
    std::cout << "Reader " << id << " sees value: " << shared_data << std::endl;
}

// 写操作
void write_data(int id, int value) {
    std::unique_lock<std::shared_mutex> lock(rw_mutex);  // 获取独占锁
    std::cout << "Writer " << id << " is writing value: " << value << std::endl;
    shared_data = value;
    std::this_thread::sleep_for(std::chrono::milliseconds(100));  // 模拟写操作
}

int main() {
    const int num_readers = 5;
    const int num_writers = 2;

    std::vector<std::thread> readers;
    std::vector<std::thread> writers;

    // 创建读线程
    for (int i = 0; i < num_readers; ++i) {
        readers.emplace_back(read_data, i);
    }

    // 创建写线程
    for (int i = 0; i < num_writers; ++i) {
        writers.emplace_back(write_data, i, i + 100);
    }

    // 等待所有线程完成
    for (auto& t : readers) {
        t.join();
    }
    for (auto& t : writers) {
        t.join();
    }

    std::cout << "Final shared data value: " << shared_data << std::endl;
    std::cout << "Main thread exits!" << std::endl;

    return 0;
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值