SDL多线程与锁机制

一、简介

为什么要用多线程?在音视频领域主要是实现音视频同步。实现了音视频同步,我们的播放器就基本上合格了。
多线程的好处主要是能使程序更加充分利用硬件(主要是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);
}
 

本文福利, 免费领取C++音视频学习资料包+学习路线大纲、技术视频/代码,内容包括(音视频开发,面试题,FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,编解码,推拉流,srs)↓↓↓↓↓↓见下面↓↓文章底部点击免费领取↓↓ 

猜你喜欢

转载自blog.csdn.net/m0_73443478/article/details/134751426
今日推荐