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(); }