qt-线程竞争共享资源和读写锁--QReadWriteLock

news2024/9/20 6:12:02

目录

  • 一、线程竞争的概念
    • 2、什么是线程竞争
    • 2、什么是线程竞争共享资源?
  • 二、读写锁
    • 1、读写锁的概念
    • 2、读写锁的工作原理如下:
    • 3、使用读写锁的示例(QReadWriteLock)
  • 三、总结:


一、线程竞争的概念

2、什么是线程竞争

线程竞争指的是在多线程环境下,多个线程同时访问和修改共享资源时可能引发的问题。
当多个线程同时竞争对同一资源进行读写或修改操作时,可能会导致不可预测的结果,包括程序崩溃、数据损坏或逻辑错误等。

线程竞争可能导致的问题包括:

  • 数据竞争:多个线程同时读写共享变量,导致数据的值无法预测或出现错误结果
  • 竞态条件:多个线程执行的顺序和时机不确定,导致最终结果与期望不符。
  • 死锁:多个线程相互等待对方释放资源,导致程序无法继续执行。
  • 活锁:多个线程无法取得进展,每个线程都在不断重试,但无法完成任务。
  • 饥饿:某个线程无法获取到需要的资源,导致一直无法执行。

为了避免线程竞争带来的问题,需要使用适当的同步机制和技术,例如互斥锁、条件变量、原子操作等,来保护共享资源的访问、修改和使用过程。正确地设计和实现多线程编程是确保程序安全性和稳定性的重要一步。

2、什么是线程竞争共享资源?

  • 在线程并发编程中,当多个线程同时访问和修改共享资源时,就会发生线程竞争。
  • 共享资源可以是数据结构、变量、文件或其他可被多个线程访问的对象。

线程竞争共享资源可能会导致以下问题:

  • 数据不一致:当多个线程同时读写共享资源时,它们可能会产生不一致的结果。例如,一个线程正在读取数据,而另一个线程正在同时修改该数据,这可能导致读取到的数据是过时或不正确的。
    一个读取,一个写入

  • 数据丢失:如果多个线程同时写入共享资源,其中一个线程的写入结果可能会被其他线程的写入覆盖,从而导致数据丢失。
    在这里插入图片描述

  • 程序崩溃:线程竞争还可能导致程序崩溃或死锁。当多个线程在访问共享资源时,如果它们无法正确同步和互斥地进行访问,就可能导致死锁情况,其中线程相互等待对方释放资源,从而无法继续执行。

二、读写锁

1、读写锁的概念

  • 读写锁是一种线程同步机制,用于解决多线程环境下的读写竞争问题
  • 读写锁允许多个线程同时获取读锁(共享访问)但只允许一个线程获取写锁(独占访问)
  • 这种机制可以提高并发性能,因为多个线程可以同时读取共享资源而不会相互干扰

2、读写锁的工作原理如下:

  • 当线程希望读取共享资源时,它们可以获取读锁。多个线程可以同时持有读锁,因此它们可以并行地读取共享资源。
    在这里插入图片描述

  • 当线程希望修改(写入)共享资源时,它必须获取写锁。写锁是独占的,即只允许一个线程持有写锁,其他线程无法获取读锁或写锁。这确保了在写入操作期间的独占访问,防止其他线程同时读取或写入共享资源

  • 当一个线程持有写锁时,其他线程的读锁和写锁请求会被阻塞,直到写锁被释放。
    在这里插入图片描述

  • 通过使用读写锁,可以有效地解决线程竞争共享资源的问题,提高程序的并发性能和稳定性。

3、使用读写锁的示例(QReadWriteLock)

在多线程编程中,使用读写锁需要注意以下几点:

  1. 根据实际情况确定锁的粒度:锁的粒度应该尽可能小,以允许更多的并发访问。如果锁的粒度太大,可能会导致并发性能下降。

  2. 正确获取和释放锁的顺序:当使用多个锁时,需要确保以正确的顺序获取和释放锁,以避免死锁或竞态条件问题。

下面是一个简单的示例,演示如何在C++中使用Qt的读写锁(QReadWriteLock)来保护共享资源的安全访问:

example.h

#ifndef EXAMPLE_H
#define EXAMPLE_H

#include <QObject>
#include <QThread>
#include <QReadWriteLock>

class Example : public QObject
{
    Q_OBJECT

public:
    explicit Example(QObject *parent = nullptr);
    ~Example();

    void start();

private:
    QReadWriteLock m_rwLock;    // 读写锁
    int m_sharedData;			// 共享资源

signals:
    void dataRead(int value);		// 读数据
    void dataWritten(int value);	// 写数据

public slots:
    void readData();             
    void writeData();
};

#endif // EXAMPLE_H

example.cpp

#include "example.h"
#include <QDebug>

Example::Example(QObject *parent) : QObject(parent)
{
    m_sharedData = 0;   // 初始化变量=0
}

Example::~Example()
{
}

// 开启线程
void Example::start()
{
    QThread readerThread;
    QThread writerThread;

    connect(&readerThread, &QThread::started, this, &Example::readData);
    connect(&writerThread, &QThread::started, this, &Example::writeData);

    readerThread.start();
    writerThread.start();
}

void Example::readData()
{
    while (true) {
        m_rwLock.lockForRead();
        qDebug() << "Read Data:" << m_sharedData;
        m_rwLock.unlock();
        QThread::msleep(500);
    }
}

void Example::writeData()
{
    while (true) {
        m_rwLock.lockForWrite();
        m_sharedData++;
        qDebug() << "Write Data:" << m_sharedData;
        m_rwLock.unlock();
        QThread::msleep(1000);
    }
}

在上述示例中,我们创建了一个共享的整数变量sharedData,并使用QReadWriteLock来保护其访问。
readData函数使用读锁定时读取共享数据,writeData函数使用写锁定时增加共享数据。

通过使用读写锁,我们确保了在读取共享资源时可以并发地访问,而在写入共享资源时只允许一个线程独占访问,从而解决了线程竞争共享资源的问题。

三、总结:

在线程并发编程中,线程竞争共享资源是一个常见的问题,可能导致数据不一致、数据丢失或程序崩溃等严重后果。
使用读写锁是一种有效的解决方案,它允许多个线程同时读取共享资源,但只允许一个线程写入共享资源。这样可以提高程序的并发性能和稳定性。

希望本篇博客对您有所帮助!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/714831.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

网络安全进阶学习第五课——文件上传漏洞

文章目录 一、常见文件上传点二、任意文件上传漏洞三、任意文件上传危害四、webshell五、上传木马所需条件六、木马上传流程七、上传绕过1、绕过JS验证1&#xff09;Burpsuite剔除响应JS。2&#xff09;浏览器审计工具剔除JS 2、绕过MIME-Type验证1&#xff09;利用抓包工具&am…

Session 反序列化漏洞

将$_SESSION中保存的所有数据序列化存储到PHPSESSID对应的文件中有三种存取格式&#xff1a; &#xff08;1&#xff09;默认使用php&#xff1a;键名|键值&#xff08;经过序列化函数处理的值&#xff09; name|s:6:"1FonlY"; &#xff08;2&#xff09;php_seri…

Multi-level Wavelet-CNN for Image Restoration论文总结

论文&#xff1a;Multi-level Wavelet-CNN for Image Restoration 源码&#xff1a;GitHub - lpj0/MWCNN: Multi-level Wavelet-CNN for Image Restoration 目录 一、背景和出发点 二、创新点 三、MWCNN具体实现 四、DWT与池化运算和膨胀卷积相关性证明 五、DWT、IWT代码实…

阿里云服务器白嫖教程

阿里云服务器白嫖教程 第一步:打开百度第二步:进入阿里云官方,注册登录账号第三步:点击免费试用第四步:点击立即试用第五步:选择操作系统第五步:选择到期释放设置![在这里插入图片描述](https://img-blog.csdnimg.cn/d02f4582dd5943319441df9ccbae60f0.png)第六步:同意协议,并立…

3D深度视觉与myCobot 320机械臂无序抓取

今天我记录使用myCobot320 M5跟FS820-E1深度相机进行一个无序抓取物体的分享。 为什么会选择深度相机和机械臂做一个案例呢&#xff1f; 2D相机&#xff08;最常见使用的相机&#xff09;可以捕捉二维图像&#xff0c;也就是在水平和垂直方向上的像素值。它们通常用于拍摄静态…

F#奇妙游(5):计算π的值

F#到底有什么用&#xff1f; 奇妙游写到第五篇&#xff0c;前面的几篇都是开场白&#xff1a; 一个用F#编写WinForm的例子donet命令行工具&#xff0c;也就是F#的开发环境关于函数和函数式编程的碎碎念函数式编程的核心概念&#xff1a;值 下面&#xff0c;我们开始正式来搞…

数据库左、右、内、逗号、全连接(mysql不包含全连接)方式

1、准备数据 学生有归属班级 学生表 班级表 2、执行查询语句 2.1执行左关联 select * from student stu left join class cla on (stu.class_idcla.class_id); 结果如下 2.2执行右关联 2.3、执行内连接 2.4执行逗号分隔表的连接方式 和内连接的查询结果是一样的

实训笔记7.3

实训笔记7.3 7.3一、座右铭二、单例模式三、IDEA集成开发环境的安装和基本使用四、Debug断点调试4.1 作用有两个4.2 用法&#xff1a;4.3 IDEA设置step into进入JDK源码4.4 step over4.5 step into 五、Java中的网络编程5.1 网络编程的三个核心要素5.2 通过Java实现网络编程 7.…

第三章 搜索与图论(二)——最短路问题

文章目录 单源最短路朴素Dijkstra堆优化版DijkstraBellman Ford算法SPFASPFA求负环 多源汇最短路Floyd 最短路练习题849. Dijkstra求最短路 I850. Dijkstra求最短路 II853. 有边数限制的最短路851. spfa求最短路852. spfa判断负环854. Floyd求最短路 源点表示起点&#xff0c;汇…

Linux系统远程挂载Mac OS系统目录方法

打开mac文件共享功能 开启共享服务 进入系统偏好设置中的共享选项。勾中文件共享&#xff08;如下图&#xff09;&#xff0c;之后右边的文件共享的绿灯会点亮&#xff0c;并显示“文件共享&#xff1a;打开”。 添加共享目录 点击在文件共享界面&#xff08;如下图&#x…

【狂神】MySQL - 数据库级别的外键

1. 外键 FOREIGN KEY (了解) 测试数据 &#xff1a; 学生表 CREATE TABLE IF NOT EXISTS student (id INT(4) NOT NULL AUTO_INCREMENT COMMENT 学号,name VARCHAR(30) NOT NULL DEFAULT 匿名 COMMENT 姓名,pwd VARCHAR(20) NOT NULL DEFAULT 123456 COMMENT 密码,sex VARC…

【数据结构与算法】 完成用十字链表存储的稀疏矩阵的加法运算

题目&#xff1a; Qestion: 完成用十字链表存储的稀疏矩阵的加法运算。 主要思路&#xff1a; 获取两个稀疏矩阵总有多少个非零元素&#xff0c;记作cnt。当cnt 不为零时一直循环&#xff0c;每循环一次i&#xff0c;也就是行循环&#xff0c;每循环一次就转移至下一行。先从…

Git常用指令总结

1、git init&#xff1a;初始化一个Git仓库&#xff1b; 2、git clone&#xff1a;从远程仓库克隆代码到本地&#xff1b; 直接使用网址 git clone <url>or 用a代替网址 git remote add a <url>git clone a3、git add&#xff1a;添加文件到暂存区&#xff1b; 文件…

K8S数据管理

K8S数据管理 1 数据管理1.1 数据持久化1.1.1 存储方案1.1.2 EmptyDir实践1.1.3 hostPath实践1.1.4 NFS实践 1.2 持久化进阶1.2.1 数据对象1.2.2 PV&PVC实践1.2.3 SC解析1.2.4 SC实践 1.3 配置管理1.3.1 配置基础1.3.2 CM1.3.3 CM案例1.3.4 Secret1.3.5 Secret案例 1.4 状态…

36. QT中使用QFtp实现文件传输1 -- 本地文件或文件夹上传到远程服务器

1. 说明 在使用QT进行嵌入式开发或者是使用到TCP控制传输时,有时程序的正常运行会用到某一个文件或者整个文件夹,此时就需要软件方面将需要的文件或者文件夹传输到远程服务器上。在QT中主要有两种方式可以实现这个功能,一个是QT4中使用QFtp这个类来实现,这个类提供了很丰富…

每天一点Python——day48

#第四十八天 #什么是元组为什么元组没有增删改操作和生成式&#xff1f; 元组&#xff1a;Python内置的数据结构之一&#xff0c;是一个不可变序列 不可变序列&#xff1a;没有增删改操作【例如字符串&#xff0c;元组】 可变序列&#xff1a;可以执行增删改操作&#xff0c;操…

记录好项目D21

记录好项目 你好呀&#xff0c;这里是我专门记录一下从某些地方收集起来的项目&#xff0c;对项目修改&#xff0c;进行添砖加瓦&#xff0c;变成自己的闪亮项目。修修补补也可以成为毕设哦 本次的项目是个基于Springbootvue的景区旅游系统 一、系统介绍 本项目分为管理员与…

534 · 打劫房屋 II

链接&#xff1a;LintCode 炼码 - ChatGPT&#xff01;更高效的学习体验&#xff01; 题解&#xff1a;九章算法 - 帮助更多程序员找到好工作&#xff0c;硅谷顶尖IT企业工程师实时在线授课为你传授面试技巧 处理循环数组问题&#xff1a;分类&#xff0c;重复&#xff0c;取反…

信息安全概述笔记

保密性、完整性、可用性是传统的信息安全的原则和目标&#xff0c;目前随着信息安全问题的日益严峻&#xff0c;信息安全的原则和目标衍生为诸如可控性、不可否认性等其他的原则和目标。 保密性&#xff08;Confidentiality&#xff09;:确保信息只能由那些被授权使用的人获取…

Web服务器群集:四层代理与七层代理

目录 一、理论 1.OSI七层模型 2.四层代理 3.七层代理 4.四层代理与七层代理区别 5.负载均衡器 6.常见的代理组件 7.应用场景 二、总结 一、理论 1.OSI七层模型 &#xff08;1&#xff09;概念 标准的七层网络分层是OSI七层模型&#xff0c;TCP/IP五层模型和TCP/IP四…