美文网首页
29_SDL 多线程与锁机制

29_SDL 多线程与锁机制

作者: 咸鱼Jay | 来源:发表于2022-11-14 13:43 被阅读0次

    一、简介

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

          本文链接:https://www.haomeiwen.com/subject/rbdlxdtx.html