一、简介

为什么要用多线程?在音视频领域主要是实现音视频同步。实现了音视频同步,我们的播放器就基本上合格了。

多线程的好处主要是能使程序更加充分利用硬件(主要是CPU)的性能。但是也存在相应的隐患,如果多线程管理不好,会出现协调问题。

这里我们将讲解一下SDL的多线程与锁机制。

引进的机制:线程的互斥与同步

  • 互斥:同一个资源在一定时间内只能由一个方法访问。
  • 同步:一个方法完成后的内容需要同步到其他的方法,在由其他方法操作完成后的内容。
  • 锁与信号量
  • 锁用于完成互斥;信号量用于同步。
  • 锁的种类:读写锁、自旋锁、可重入锁。
SDL线程创建:SDL_CreateThread 

SDL线程等待:SDL_WaitThead

SDL互斥锁:SDL_CreateMutex / SDL_DestroyMutex

SDL锁定互斥:SDL_LockMutex / SDL_UnlockMutex

SDL 条件变量(信号量):SDL_CreateCond / SDL_DestoryCond

SDL 条件变量(信号量)等待 / 通知 :SDL_CondWait / SDL_CondSingal

二、代码实现:

我们通过SDL的锁机制实现生产者和消费者

2.1、声明

//mainwindow.h

Ui::MainWindow *ui;
/** 互斥锁*/
SDL_mutex *_mutex = nullptr;
/** 条件变量:消费者等待,生产者唤醒 */
SDL_cond *_cond = nullptr; std::list<QString> *_list = nullptr;
int _index = 0; void consume(QString name);
void produce(QString name);

2.2、创建锁、消费者

//mainwindow.cpp

// 创建互斥锁
_mutex = SDL_CreateMutex();
// 创建条件变量
_cond = SDL_CreateCond(); // 创建链表
_list = new std::list<QString>(); // 创建消费者
consume("消费者1");
consume("消费者2");
consume("消费者3");
consume("消费者4");

2.3、销毁

MainWindow::~MainWindow(){
delete ui;
delete _list;
SDL_DestroyMutex(_mutex);
SDL_DestroyCond(_cond);
}

2.4、实现生产者逻辑

void MainWindow::produce(QString name){
std::thread([this,name](){
SDL_LockMutex(_mutex); qDebug() << name << "开始生产"; _list->push_back(QString("%1").arg(++_index));
_list->push_back(QString("%1").arg(++_index));
_list->push_back(QString("%1").arg(++_index)); // 唤醒消费者:赶紧开始消费
SDL_CondSignal(_cond); SDL_UnlockMutex(_mutex);
}).detach();
}

2.5、实现销毁者逻辑

void MainWindow::consume(QString name){
std::thread([this,name](){
SDL_LockMutex(_mutex);
while (true) {
qDebug() << name << "开始消费";
while (!_list->empty()) {
qDebug() << _list->front();
// 删除头部
_list->pop_front();
// 睡眠500ms
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
/**
* 1.释放互斥锁
* 2.等待条件_cond
* 3.等到了条件_cond、加锁
*/
SDL_CondWait(_cond,_mutex);
}
SDL_UnlockMutex(_mutex);
}).detach();
}

2.6、创建生产者

void MainWindow::on_produceBtn_clicked(){
// 创建生产者
produce("生产者1");
produce("生产者2");
produce("生产者3");
}

三、分装SDL锁机制

我们可以将SDL的锁机制的api进行二度分装,以便后面的音视频使用

condmutex.h

#ifndef CONDMUTEX_H
#define CONDMUTEX_H #include <SDL2/SDL.h> class CondMutex {
public:
CondMutex();
~CondMutex(); void lock();
void unlock();
void signal();
void broadcast();
void wait(); private:
/** 互斥锁 */
SDL_mutex *_mutex = nullptr;
/** 条件变量 */
SDL_cond *_cond = nullptr;
}; #endif // CONDMUTEX_H

condmutex.cpp

#include "condmutex.h"

CondMutex::CondMutex(){
// 创建互斥锁
_mutex = SDL_CreateMutex();
// 创建条件变量
_cond = SDL_CreateCond();
} CondMutex::~CondMutex(){
SDL_DestroyMutex(_mutex);
SDL_DestroyCond(_cond);
} void CondMutex::lock(){
SDL_LockMutex(_mutex);
} void CondMutex::unlock(){
SDL_UnlockMutex(_mutex);
} void CondMutex::signal(){
SDL_CondSignal(_cond);
} void CondMutex::broadcast(){
SDL_CondBroadcast(_cond);
} void CondMutex::wait(){
SDL_CondWait(_cond,_mutex);
}

代码链接1

代码链接2

29_SDL多线程与锁机制的更多相关文章

  1. SDL 开发实战(七): SDL 多线程与锁机制

    为什么要用多线程?在音视频领域主要是实现音视频同步.实现了音视频同步,我们的播放器就基本上合格了. 这里我们将讲解一下SDL的多线程与锁机制. 多线程的好处主要是能使程序更加充分利用硬件(主要是CPU ...

  2. C 语言多线程与锁机制

    C 语言多线程与锁机制 多线程 #include <pthread.h> void *TrainModelThread(void *id) { ... pthread_exit(NULL) ...

  3. JAVA多线程与锁机制

    JAVA多线程与锁机制 1 关于Synchronized和lock synchronized是Java的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码 ...

  4. Java多线程(二) 多线程的锁机制

    当两条线程同时访问一个类的时候,可能会带来一些问题.并发线程重入可能会带来内存泄漏.程序不可控等等.不管是线程间的通讯还是线程共享数据都需要使用Java的锁机制控制并发代码产生的问题.本篇总结主要著名 ...

  5. java多线程(三)——锁机制synchronized(同步语句块)

    用关键字synchronized声明方法在某些情况下是有弊端的,比如A线程调用同步方法之行一个长时间的任务,那么B线程必须等待比较长的时间,在这样的情况下可以使用synchronized同步语句快来解 ...

  6. java多线程(二)——锁机制synchronized(同步方法)

    synchronized Java语言的关键字,可用来给对象和方法或者代码块加锁,当它锁定一个方法或者一个代码块的时候,同一时刻最多只有一个线程执行这段代码.当两个并发线程访问同一个对象object中 ...

  7. Lucene的多线程访问原则和同步,锁机制

    本文介绍lucene多线程环境下的使用原则和commit.lock与write.lock实现的锁机制. 设计之初就是服务于多线程环境,大多数情况下索引会被不至一个线程访问.索引时一个关键资源.在对这样 ...

  8. [java多线程] - 锁机制&同步代码块&信号量

    在美眉图片下载demo中,我们可以看到多个线程在公用一些变量,这个时候难免会发生冲突.冲突并不可怕,可怕的是当多线程的情况下,你没法控制冲突.按照我的理解在java中实现同步的方式分为三种,分别是:同 ...

  9. Java CAS同步机制 原理详解(为什么并发环境下的COUNT自增操作不安全): Atomic原子类底层用的不是传统意义的锁机制,而是无锁化的CAS机制,通过CAS机制保证多线程修改一个数值的安全性。

    精彩理解:  https://www.jianshu.com/p/21be831e851e ;  https://blog.csdn.net/heyutao007/article/details/19 ...

  10. Java多线程5:Synchronized锁机制

    一.前言 在多线程中,有时会出现多个线程对同一个对象的变量进行并发访问的情形,如果不做正确的同步处理,那么产生的后果就是“脏读”,也就是获取到的数据其实是被修改过的. 二.引入Synchronized ...

随机推荐

  1. linux 后台运行进程:& , nohup

    目录 后台执行 & nohup 查看后台运行的命令 jobs ps 关闭当前后台运行的程序 kill 前后台进程的切换与控制 ctrl + z 命令 fg 命令 bg 命令 思考 问题1-为什 ...

  2. JuiceFS v1.0 正式发布,首个面向生产环境的 LTS 版本

    今天,JuiceFS v1.0 发布了 经过了 18 个月的持续迭代和大量生产环境的广泛验证,此版本将成为第一个被长期维护的稳定版(LTS).同时,该版本提供完整的向前兼容,所有用户可以直接升级. J ...

  3. .NET Core开发实战(第28课:工作单元模式(UnitOfWork):管理好你的事务)--学习笔记

    28 | 工作单元模式(UnitOfWork):管理好你的事务 工作单元模式有如下几个特性: 1.使用同一上下文 2.跟踪实体的状态 3.保障事务一致性 我们对实体的操作,最终的状态都是应该如实保存到 ...

  4. MySQL8-[问题解决]java.sql.SQLNonTransientConnectionException: Cannot load connection class because of underlying

    对应为MySQL8和 MySQL-connecter8.0.16 1.修改MySQL驱动器 原来的版本: com.mysql.jdbc.Driver 现在改为:com.mysql.cj.jdbc.Dr ...

  5. CentOS7环境源码安装freeswitch1.10.7

    操作系统 :CentOS 7.6_x64 freeswitch版本 :1.10.7 一.安装步骤 1.下载freeswitch源代码 wget http://files.freeswitch.org/ ...

  6. ABC 304

    T4 在一个平面上有一块面积无限的蛋糕,给出 \(n\) 颗草莓的所在位置和 \(a\,(b)\) 条平行与 \(x\,(y)\) 轴的切刀位置. 切刀会把蛋糕沿 \(x\,(y)\) 轴切开.因此一 ...

  7. CF1878C Vasilije in Cacak 题解

    题目传送门 简化题意 有 \(t\) 组询问,每次询问是否能从 \(1 \sim n\) 中选择 \(k\) 个数使得它们的和为 \(x\). 解法 考虑临界情况,从 \(1 \sim n\) 中选择 ...

  8. JS leetcode 两数之和解答思路分析

    壹 ❀ 引 在学习算法基础的同时,我还是继续捡起leetcode的算法题了,珍惜时间,算法每天进步一点点.不得不说,在了解了一些算法概念后,至少有些答案是能看懂了......(惭愧)虽然我很菜,但是多 ...

  9. NC50454 A Simple Problem with Integers

    题目链接 题目 题目描述 给定数列 \(a[1],a[2], \dots,a[n]\) ,你需要依次进行q个操作,操作有两类: 1 l r x:给定l,r,x,对于所有 \(i \in[l,r]\) ...

  10. NC53074 Forsaken喜欢独一无二的树

    题目链接 题目 题目描述 ​ 众所周知,最小生成树是指使图中所有节点连通且边权和最小时的边权子集. ​ 不过最小生成树太简单了,我们现在来思考一个稍微复杂一点的问题. ​ 现在给定一个 \(n\) 个 ...