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

作者:阅遍星辰任是少年
链接: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();

}

上一篇:SSM 项目 Library Manager System


下一篇:pmp错题集2(强化三)