ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

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

2021-09-04 09:59:01  阅读:178  来源: 互联网

标签:信号量 capacity Qt int 间通信 manager mutex include public


作者:阅遍星辰任是少年
链接:https://www.nowcoder.com/discuss/389380?type=1
来源:牛客网
 

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

APP内打开 0 3 0 分享

1、进程与线程的基础知识

2、qt进程通信的共享内存

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

类方法:

复制代码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

//.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

复制代码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

//.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的用法
 

复制代码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

//扩展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

复制代码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

#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

复制代码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

#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

复制代码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

#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

复制代码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

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

}

标签:信号量,capacity,Qt,int,间通信,manager,mutex,include,public
来源: https://blog.csdn.net/yantuguiguziPGJ/article/details/120095445

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有