Qt进程间通信及内存共享,信号量,锁机制,线程同步

1、进程与线程的基础知识
2、qt进程通信的共享内存
概念:共享内存指 (shared memory)在多处理器的计算机系统中,可以被不同中央处理器(CPU)访问的大容量内存。由于多个CPU需要快速访问存储器,这样就要对存储器进行缓存(Cache)。任何一个缓存的数据被更新后,由于其他处理器也可能要存取,共享内存就需要立即更新,否则不同的处理器可能用到不同的数据。共享内存是Unix下的多进程之间的通信方法 ,这种方法通常用于一个程序的多进程间通信,实际上多个程序间也可以通过共享内存来传递信息。
类方法:
//.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <iostream>
#include <QSharedMemory>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
protected:
    void loadfrommem();
    void loadfromfile();



private slots:
    void on_pushButton_mem_clicked();

private:
    Ui::MainWindow *ui;
    QSharedMemory shareMemory;
};

#endif // MAINWINDOW_H
//.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QFileDialog>
#include <QBuffer>
#include <string>
#include <QPixmap>
#include <iostream>
#include <QDebug>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    shareMemory.setKey("share");
    connect(ui->pushButton_mem,QPushButton::clicked,this,MainWindow::loadfrommem);
    connect(ui->pushButton_file,QPushButton::clicked,this,MainWindow::loadfromfile);

}

MainWindow::~MainWindow()
{
    delete ui;
}


void MainWindow::loadfromfile()
{

    if(shareMemory.isAttached())
    {
        shareMemory.detach();//将该进程与共享内存分离
    }
    QString filename=QFileDialog::getOpenFileName(this);
    QPixmap pixmap;
    pixmap.load(filename);//从文件中找到图片

    QBuffer buffer;//建立缓存对象
    QDataStream out(&buffer);//数据流操作,用于操作缓存的数据
    buffer.open(QBuffer::ReadWrite);//打开qbuffer的读写权限
    out<<pixmap;//输出piamap
    qDebug()<<buffer.size();

    int size=buffer.size();
    if(!shareMemory.create(size))
    {
         qDebug()<<tr("can not creat memory sqgment");
          qDebug()<<shareMemory.error();
          return;
    }
    qDebug()<<shareMemory.size();
/*****************************************************************************/
    //共享内存部分上锁,使用内存段
    shareMemory.lock();
    char *to=(char*)shareMemory.data();
    const char*from=(char*)buffer.data().data();
    memcpy(to,from,qMin(size,shareMemory.size()));//数据从该进程中拷贝到共享数据内存中
    shareMemory.unlock();
/*****************************************************************************/
}



void MainWindow::loadfrommem()
{
  if(!shareMemory.attach())
  {
       qDebug()<<tr("can not creat memory sqgment");

  }
  QBuffer buffer;
  QDataStream in(&buffer);
  QPixmap pixmap;
  /*****************************************************************************/
  shareMemory.lock();
  buffer.setData((char*)shareMemory.constData(),shareMemory.size());//将sharememory里面的数据放到buffer之中
  buffer.open(QBuffer::ReadWrite);
  in>>pixmap;
  shareMemory.unlock();
  shareMemory.detach();//将sharememeory与该进程分离
  ui->label->setPixmap(pixmap);
  /*****************************************************************************/
}
扩展findChildren的用法

//扩展findChildren的用法
//主线程
void MainWindow::buttonclicked()
{
//    QToolButton* btns = this->findChild<QToolButton*>(QString("btn%1").arg(i));
    QList<QToolButton*> btns=this->findChildren<QToolButton*>();

    qDebug()<<btns;
    foreach (QToolButton*btn, btns) {
        connect(btn,&QToolButton::clicked,measureThread,&MeasureThread::setTwoRelay);
    }

}

//子线程
void MeasureThread::setTwoRelay()
{
    QToolButton *btn=(QToolButton*)sender();
    QString puttonName=btn->objectName();
    QStringList puttonlist = puttonName.split("_");
    realayNameBegin=puttonlist.at(1);
    realayNameEnd=puttonlist.at(2);
    SwitchRelay();

    //    QStringList list;
    //    QVector<int> v;
    //    for(int i=1;i<25;i++)
    //    {
    //        v.push_back(i);
    //    }
    //    for(int i=0;i<v.size();i++)
    //    {
    //       int x=v[i];
    //       QString temp=QString::number(x);
    //       list.append(temp);

    //    }
}
3、线程同步
线程同步典型例子“生产者-消费者模型”,也称有限缓冲问题
qt解决线程同步三个方法

(1)、信号量
使用类:QSemaphore
概念:pv操作,加减

(2)、进程类/锁机制
  • QMutex/QMutexLocker
  • QWaitCondtion
多线程使用的锁机制
MutexOnly
#ifndef MUTEXONLY_H
#define MUTEXONLY_H

#include <QCoreApplication>
#include <iostream>
#include <QTime>
#include <QMutex>
#include <QThread>
#include <QWaitCondition>

using namespace std;
class MutexOnly
{
public:
//    MutexOnly();
    //预计生产(或消费)数量
    int loopCount;
    //当前产品数量
    int product;
    //仓库能容纳最大产品数量
    int capacity;

    QMutex mutex;


    //QWaitCondition类为线程同步提供了一个条件变量,此处设置条件

    QWaitCondition productIsNotFull;//商店产品不是满的
    QWaitCondition productIsNotEmpty;//商店产品不为空

    //生产者**********************************************************************************

    class Producer:public QThread
    {
    public:
        Producer(MutexOnly *manager) : QThread() {
            this->manager=manager;

    }
    protected:
        void run(){
            for(int i=0;i<manager->loopCount;i++)
            {
                manager->mutex.lock();
                while(manager->product==manager->capacity)
                {
                    //释放该锁,并且阻塞当前线程,直到条件满足(即调用wake方法被唤醒)
                    manager->productIsNotFull.wait(&manager->mutex);
                }
                manager->product++;
                cout<<i<<".P"<<manager->product<<", ";
                manager->productIsNotEmpty.wakeAll();
                manager->mutex.unlock();
            }
        }
    private:
        MutexOnly *manager;
    };




    /****消费者************************************************************************/

    class Consumer:public QThread{

    public:
        Consumer(MutexOnly *manager):QThread(){

            this->manager=manager;

        }

    protected:
        void run(){
            for(int i; i<manager->loopCount;i++)
            {
                manager->mutex.lock();
                while(manager->product==0){
                    manager->productIsNotEmpty.wait(&manager->mutex);
                }
                manager->product--;
                cout<<i<<",C="<<manager->product<<", ";
                manager->productIsNotFull.wakeAll();
                manager->mutex.unlock();
            }

        }

    private:
        MutexOnly *manager;
    };

     /****无修饰方法************************************************************************/
public:
    void test(int loopCount,int capacity)
    {
        this->loopCount=loopCount;
        this->capacity=capacity;
        this->product=0;

        Producer producer(this);
        Consumer consumer(this);
        //thread.start会调用thread内部的run方法
        producer.start();
        consumer.start();



        //接下来阻塞该线程直到所有条件都满足
        producer.wait();
        consumer.wait();
        cout<<endl;

    }

};

#endif // MUTEXONLY_H

MutexWaitCondition
#ifndef MUTEXWAITCONDITION_H
#define MUTEXWAITCONDITION_H

#include <QCoreApplication>
#include <iostream>
#include <QTime>
#include <QMutex>
#include <QThread>
#include <QWaitCondition>

using namespace std;

class MutexWaitCondition
{
public:
    MutexWaitCondition();

public :
    //预计生产(或消费)数量
    int loopCount;
    //当前产品数量
    int product;
    //仓库能容纳最大产品数量
    int capacity;

    QMutex mutex;


    //QWaitCondition类为线程同步提供了一个条件变量,此处设置条件

    QWaitCondition productIsNotFull;//商店产品不是满的
    QWaitCondition productIsNotEmpty;//商店产品不为空

    /*生产者**********************************************************************************/
    class Producer:public QThread
    {
    public:
        Producer(MutexWaitCondition *manager) : QThread() {
            this->manager=manager;

    }
    protected:
        void run(){
            for(int i=0;i<manager->loopCount;i++)
            {
                manager->mutex.lock();
                while(manager->product==manager->capacity)
                {
                    //释放该锁,并且阻塞当前线程,直到条件满足(即调用wake方法被唤醒)
                    manager->productIsNotFull.wait(&manager->mutex);
                }
                manager->product++;
                cout<<i<<".P"<<manager->product<<", ";
                manager->productIsNotEmpty.wakeAll();
                manager->mutex.unlock();
            }
        }
    private:
        MutexWaitCondition *manager;
    };




    /****消费者************************************************************************/


    class Consumer:public QThread{

    public:
        Consumer(MutexWaitCondition *manager):QThread(){

            this->manager=manager;

        }

    protected:
        void run(){
            for(int i; i<manager->loopCount;i++)
            {
                manager->mutex.lock();
                while(manager->product==0){
                    manager->productIsNotEmpty.wait(&manager->mutex);
                }
                manager->product--;
                cout<<i<<",C="<<manager->product<<", ";
                manager->productIsNotFull.wakeAll();
                manager->mutex.unlock();
            }

        }

    private:
        MutexWaitCondition *manager;
    };
    /****无修饰方法************************************************************************/
public:
   void test(int loopCount,int capacity)
   {
       this->loopCount=loopCount;
       this->capacity=capacity;
       this->product=0;

       Producer producer(this);
       Consumer consumer(this);
       //thread.start会调用thread内部的run方法
       producer.start();
       consumer.start();



       //接下来阻塞该线程直到所有条件都满足
       producer.wait();
       consumer.wait();
       cout<<endl;

   }







};

#endif // MUTEXWAITCONDITION_H

SenaphoreMutex
#ifndef SENAPHOREMUTEX_H
#define SENAPHOREMUTEX_H

#include <QCoreApplication>
#include <iostream>
#include <QTime>
#include <QMutex>
#include <QThread>
#include <QWaitCondition>
#include <QSemaphore>
using namespace std;

class SenaphoreMutex
{
public:
    SenaphoreMutex();
public:
    //预计生产(或消费)数量
    int loopCount;
    //当前产品数量
    int product;
    //仓库能容纳最大产品数量
    int capacity;

    QMutex mutex;

    //QSemaphore类提供一个通用的计数信号量,定义了两个信号量对象
    QSemaphore *productSemhore;
    QSemaphore *leftSpaceSemaphore;

    /*生产者*(****************************************************************************************************************/

    class  Producer : public QThread{
    public:
        Producer(SenaphoreMutex *manager): QThread() {
            this->manager=manager;

        }

    protected:
        void run()
        {
            for(int i=0; i<manager->loopCount; i++)
            {
                //尝试获取(减去)n个被信号量控制的资源,如果n大于可用资源数量,它就会阻塞直到有足够的资源为止
                manager->leftSpaceSemaphore->acquire();
                //之所以lock要在acquire后面是因为:如果消费者拿到了锁,那么又没有商品,会导致死锁
                manager->mutex.lock();
                manager->productSemhore->release();
                cout<<i<<".P"<<manager->productSemhore->available()<<",";
                manager->mutex.unlock();

            }
        }

    private:
        SenaphoreMutex *manager;
    };
    \


    /*消费者*********************************************************************************************************************/

    class Consumer : public QThread
    {
    public:
        Consumer(SenaphoreMutex *manager) :QThread(){

            this->manager=manager;


    }
    protected:
        void run(){
            for(int i=0; i<manager->loopCount;i++){
                manager->productSemhore->acquire();
                manager->mutex.lock();

                manager->leftSpaceSemaphore->release();
                cout<<i<<".C="<<manager->productSemhore->available()<<",";
                manager->mutex.unlock();


            }
        }
    private:
        SenaphoreMutex *manager;
    };



    //无修饰的方法 默认是private的****************************************************************************/
public:
    void test(int loopCount,int capacity)
    {
        this->loopCount=loopCount;
        this->capacity=capacity;

        //参数为:信号量的当前值
        productSemhore=new  QSemaphore(0);
        leftSpaceSemaphore=new  QSemaphore(capacity);

        Producer producer(this);
        Consumer consumer(this);

        //thread.start   RUN
        producer.start();
        consumer.start();

        //阻塞该线程直到所有条件都满足
        producer.wait();

    }



};

#endif // SENAPHOREMUTEX_H

#include <QCoreApplication>
#include <QTime>
#include <iostream>
#include "mutexonly.h"
#include "mutexwaitcondition.h"
#include "senaphoremutex.h"


int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    using namespace std;



    int loopCount=100;
    int capacity=3;
    QTime time;

    int mutexOnlyElapsed;
    int mutexWaitConditonElapsed;
    int SemaphoreMutexElapsed;
//    cout<<"loopCount ="<<loopCount<<"capacity ="<<capacity<<endl<<endl;
//    cout<<"MutexOnly"<<endl;

//    MutexOnly mutexOnly;
//    time.start();
//    mutexOnly.test(loopCount,capacity);

//    //milliseconds,返回最后一次调用start到现在已经经过的毫秒数
//    mutexOnlyElapsed=time.elapsed();
//    cout<<"elapsed:"<<mutexOnlyElapsed<<"ms"<<endl;
//    cout<<endl;


    cout<<"Mutexwaitcondition"<<endl;
    MutexWaitCondition mutexWaitCondition;
    time.restart();
    mutexWaitConditonElapsed=time.elapsed();

    cout<<"elapsed:"<<mutexWaitConditonElapsed<<"ms"<<endl;
    cout<<endl;



    cout<<'SemaphoreMutex'<<endl;
    SenaphoreMutex SemaphoreMutex;
    time.restart();
    SemaphoreMutex.test(loopCount,capacity);
    SemaphoreMutexElapsed=time.elapsed();
    cout<<"elapsed"<<SemaphoreMutexElapsed<<"ms"<<endl;
    cout<<endl;
    return 0;




    return a.exec();
}










#字节跳动招聘头条研发前端##求面经#
全部评论

相关推荐

感觉这一周太梦幻了,就像一个梦,很不真实~~~感觉这个暑期,我的运气占了99成,实力只有百分之一4.15上午&nbsp;腾讯csig&nbsp;腾讯云部门,面完秒进入复试状态4.16下午&nbsp;美团优选供应链部门,4.18上午发二面4.17晚上&nbsp;阿里国际一面,纯拷打,面完我都玉玉了4.18下午&nbsp;阿里国际二面,是我们leader面的我,很轻松~~4.18晚上&nbsp;约了hr面4.19上午&nbsp;hr面,下午两点口头oc4.19晚上&nbsp;意向书说起来我的暑期好像一次都没挂过~~~~~难道我是天生面试圣体?----------------------------------------------------------------------六个月前,我还是0项目0刷题,当时想的是先把论文发出来再去找实习。结果一次组会,老师打破了我的幻想(不让投B会,只让投刊或者A)我拿头投啊!!!然后就开始物色着找实习,顺便做完了mit的6.s081,但是基本上还是没刷过题目-----------------------------------------------------------------------11月&nbsp;&nbsp;一次偶然的机会,面进了某个耳机厂的手环部门,大概是做嵌入式的,用的是CPP。12月&nbsp;莫名其妙拿到了国创的面试机会,0基础四天速成java基础!居然也给我面过了hhhhh,可能是面试没写题吧入职国创后的几个月,一直没活,天天搁那看剧,都快忘了还有暑期实习这回事了~~~~命运的齿轮在2.26开始转动,因为这一天美团开了,我开始慌了,因为那时的我什么都不会。lc,八股,sql全部是0进度。然后就开始了女娲补天,上班刷题,下班继续做之前的开源,顺便学一学八股。3月到现在,lc也刷到快200了,一天最多提交了47次~~~~~~~~~~八股根据别人的面经总结和博客,写了快十万字的笔记~~~~~~~~~~简历上的实习经历和开源,也努力去深挖了,写了几万字的记录~~~~~~所以面试的时候,基本上都能cover了,面试官问到的基础基本都会,不基础的我就把他往我会的地方引。结果好像还不错,基本上每个面试官评价都挺好的emmmmmmmm
投递阿里巴巴等公司10个岗位
点赞 评论 收藏
转发
点赞 4 评论
分享
牛客网
牛客企业服务