首页 > 编程语言 >C++之共享数据

C++之共享数据

时间:2023-07-08 11:22:37浏览次数:41  
标签:std 数据 C++ 互斥 共享 include data

背景

在C++多线程编程中,线程间共享数据是一种常见的情况。然而,如果不加以处理,共享数据可能导致一些问题,如条件竞争。本文将介绍C++中多线程共享数据的方式,包括各种方式的使用场景和比较。

使用互斥锁(Mutex)

互斥锁(Mutex)是一种同步原语,用于保护共享数据的访问。当一个线程访问共享数据时,它需要先锁定互斥锁,访问完成后再解锁互斥锁。这样可以确保在同一时刻只有一个线程可以访问共享数据。

使用场景:适用于保护简单的共享数据,如整数、指针等。

#include <thread>
#include <mutex>

std::mutex mtx;
int shared_data = 0;

void increment() {
mtx.lock();
++shared_data;
mtx.unlock();
}

int main() {
std::thread t1(increment);
std::thread t2(increment);
t1.join();
t2.join();
std::cout << "Shared data: " << shared_data << std::endl;
return 0;
}

使用原子操作(Atomic)

原子操作提供了一种在底层硬件层面上确保在同一时刻只有一个线程可以访问共享数据的方法。C++11引入了std::atomic模板类,用于实现原子操作。

使用场景:适用于对简单数据类型进行原子操作,如整数、指针等。

#include <iostream>
#include <thread>
#include <atomic>

std::atomic<int> shared_data(0);

void increment() {
    ++shared_data;
}

int main() {
    std::thread t1(increment);
    std::thread t2(increment);
    t1.join();
    t2.join();
    std::cout << "Shared data: " << shared_data << std::endl;
    return 0;
}

使用条件变量(Condition Variable)

条件变量是一种同步原语,用于在线程间传递通知。当一个线程需要等待另一个线程完成某个操作时,它可以使用条件变量等待通知。

使用场景:适用于需要在线程间传递通知的场景,如生产者消费者问题。

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>

std::mutex mtx;
std::condition_variable cv;
std::queue<int> data_queue;

void producer() {
    for (int i = 0; i < 5; ++i) {
        std::unique_lock<std::mutex> lock(mtx);
        data_queue.push(i);
        std::cout << "Produced: " << i << std::endl;
        lock.unlock();
        cv.notify_one();
    }
}

void consumer() {
    while (true) {
        std::unique_lock<std::mutex> lock(mtx);
        cv.wait(lock, [] { return !data_queue.empty(); });
        int data = data_queue.front();
        data_queue.pop();
        std::cout << "Consumed: " << data << std::endl;
        if (data == 4) break;
    }
}

int main() {
    std::thread t1(producer);
    std::thread t2(consumer);
    t1.join();
    t2.join();
    return 0;
}

各种共享数据方式的比较与使用场景

  • 使用互斥锁:适用于保护简单的共享数据,易于使用,但可能导致性能开销。
  • 使用原子操作:适用于对简单数据类型进行原子操作,性能较高,但不适用于复杂数据结构。
  • 使用条件变量:适用于需要在线程间传递通知的场景,可以有效地协调线程间的执行顺序,但需要与互斥锁配合使用。

在实际应用中,我们需要根据具体的需求和场景选择合适的共享数据方式。以下是一些建议:

  • 如果共享数据简单且对性能要求不高,可以考虑使用互斥锁。
  • 如果共享数据简单且对性能要求较高,可以考虑使用原子操作。
  • 如果需要在线程间传递通知,可以考虑使用条件变量。

最后

总结一下,在这篇博客中,我们介绍了C++中多线程共享数据的方式,包括各种方式的使用场景和比较。通过合理地选择和使用共享数据方式,我们可以有效地保护共享数据,确保多线程程序的正确性和稳定性。在进行多线程编程时,我们需要了解各种共享数据方式的特点和适用场景,以便在不同场合选择合适的方式来保护共享数据。

 

标签:std,数据,C++,互斥,共享,include,data
From: https://www.cnblogs.com/blizzard8204/p/17536942.html

相关文章

  • C++之死锁
    背景在多线程编程中,死锁是一个常见的问题,它会导致程序陷入无法继续执行的状态。在这篇博客中,我们将介绍C++中死锁的概念、产生原因以及解决办法。什么是死锁?死锁是指多个线程在等待对方释放资源,导致彼此都无法继续执行的情况。死锁通常发生在多个线程同时锁定多个互斥锁的情况......
  • C++之线程管控(一)
    背景多线程编程在实际应用中非常常见,它可以帮助我们提高程序性能,实现高效的任务调度。从C++11开始,C++语言已经提供了对多线程编程的原生支持。本文将详细介绍如何使用C++进行线程管控,包括发起线程、等待线程完成、异常处理以及在后台运行线程等内容。发起线程C++11提供了一个名......
  • C++之线程管控(二)
    背景随着多核处理器的普及,多线程编程已经成为软件开发中不可或缺的一部分。C++11标准为我们带来了线程库,让我们能够更方便地在C++中实现多线程编程。在这篇博客中,我们将介绍C++线程管控的基本概念和方法,包括向线程函数传递参数,移交线程归属权,运行时选择线程数量和识别线程。向线......
  • 手把手教学小型金融知识图谱构建:量化分析、图数据库neo4j、图算法、关系预测、命名实
    手把手教学小型金融知识图谱构建:量化分析、图数据库neo4j、图算法、关系预测、命名实体识别、CypherCheetsheet详细教学等效果预览:1.知识图谱存储方式知识图谱存储方式主要包含资源描述框架(ResourceDescriptionFramework,RDF)和图数据库(GraphDatabase)。1.1资源描述框......
  • C++ Primer 学习笔记——第七章
    第七章类前言基本数据类型有时候并不能解决某些特定问题,而通过自定义的类就可以通过理解问题概念,使得程序更加容易编写、调试和修改。类的基本思想是数据抽象(dataabstraction)和封装(encapsulation)。数据抽象是一种依赖于接口(interface)和实现(implementation)分离的编程(以及设......
  • 查看sql server数据库连接情况
    SELECT*FROM[Master].[dbo].[SYSPROCESSES]WHERE[DBID]IN(SELECT[DBID]FROM[Master].[dbo].[SYSDATABASES]WHERENAME='你的数据库名称')系统存储过程SP_WHO提供关于当前 Microsoft?SQLServer?  用户和进程的信息。可以筛选返回的信......
  • C语言:数据结构之单链表(二)
    上一篇随笔谈了谈单链表是什么东西,然后进行了初始化,这篇随笔就开始对其进行操作了,首先是增,删,改,查的增。增,顾名思义就是要增加新的元素,单链表是链式的,那就要考虑怎么去加新元素,有三种,从头部添加,从尾部添加,从中间添加。先说说从尾部添加,这个比较好理解,直接在尾部放一个结点......
  • c++ 科幻版 沙漠神殿2
    #include<iostream>#include"minecraft.h"#include<string>usingnamespacestd;TxMinecraftmc;intx,y,z;boolcon;boollianjie(){ returncon=mc.ConnectMinecraft("mc.makeblock.net.cn","a9d44e758f6e4cf8b2da26241......
  • 请使用C++计算出2^2023与3^2023的和
    易知,这个和的数字是非常大的,大到longlong都装不下,这个时候如果使用longlong是无法进行运算的。欸!这会高精度算法(即大数运算)就开始发光发热了。以下是我看资料总结的一些歪瓜裂枣。对于一位高精度数字,用整数数组存储,数组每一个元素对应一位十进制数,由其下标顺序指明位序号......
  • 从“存算一体”到“存算分离”:金融核心数据库改造的必经之路
    科技云报道原创。近年来,数据库国产化趋势愈发明显,上百家金融业试点单位在数据库国产化的进程中,进一步增强信心,向50%国产化率大步迈进。但随着数据库国产化的深入,一些金融机构采用国产数据库+服务器本地盘的“存算一体”部署策略,逐渐在实践中暴露出短板,难以满足金融核心的场景需求。......