C++多线程编程

简介:

      C++的多线程不同于C语言的多线程,对于我这个从C转向C++的来说更是觉得很难理解;来新公司的这段时间也是一直在思考这方面的事情,近期一直在检查程序中死锁的问题;就总结以下最近对于C++多线程编程的心得吧。

      C++的多线程主要体现在两方面,一方面是对于全局数据的线程同步。我们看下面的实例

      首先我们封装一个Thread类

Thread.h 文件


#ifndef THREAD_H

#define THREAD_H



#include <pthread.h>



class Thread

{

public:

    Thread();



    int start();

    

    int stop();



    virtual void* run();



    bool join();



    const pthread_t& getID()const { return ntid; }



    virtual ~Thread(){};



private:

    Thread(const Thread&);



    static void* threadproc(void*);



    pthread_t ntid;



};

Thread.cpp 文件


#include <pthread.h>

#include "Thread.h"



Thread::Thread()

{

}



void* Thread::run()

{

      

}



int Thread::start()

{

    return pthread_create(

            &this->ntid,

            0,

            threadproc,

            static_cast<void *>(this)

            );        

}



int Thread::stop()

{

    return pthread_cancel(this->getID());

}



bool Thread::join()

{

    return pthread_join(this->getID(),0);

}



void* Thread::threadproc(void* a_param)

{

    Thread* pthread = static_cast<Thread *>(a_param);

    return pthread->run();

      然后我们新建MyThread类,继承自Thread类,以实现不同的算法。

MyThread.h


#ifndef MYTHREAD_H

#define MYTHREAD_H



#include <string>

#include "Thread.h"



class MyThread:public Thread

{

public:

    MyThread(const int n,const char* aName):mCount(n),mName(aName){};

    virtual void* run();



    int setCount(const int n);



    int setName(const char* aName);



private:

    int mCount;

    std::string mName;

};

MyThread.cpp


#include <string>

#include <stdio.h>

#include <boost/thread/thread.hpp>

#include "MyThread.h"



void* MyThread::run() 

{

    int sum = this->mCount*10;

    for(int i = 0;i < sum ;i++)

    {

        printf("%2d,the name is %s;\t\n",i,this->mName.c_str());

    }

}



int MyThread::setCount(const int n)

{

    this->mCount = n;

    return 0;

}



int MyThread::setName(const char* aName)

{

    std::string aString(aName);

    this->mName = aString;

    return 0;

main.cpp 


#include <stdio.h>

#include "MyThread.h"







int main()

{



    MyThread t1(15,"Thread 1");

        MyThread t2(12,"Thread 2");

    

    t1.start();

    t2.start();

    

    sleep(1);



    return 0;

Makefile文件,写的不好,大家见谅啊 


multiThread:main.o MyThread.o Thread.o

    g++ -o multiThread main.o MyThread.o Thread.o -lpthread



main.o:main.cpp MyThread.h

    g++ -c main.cpp



MyThread.o:MyThread.cpp MyThread.h Thread.h

    g++ -c MyThread.cpp



Thread.o:Thread.cpp Thread.h

    g++ -c Thread.cpp



clean:

       make并且运行之后,看下运行情况 为了节省空间我只给出了几个数据,有兴趣大家可以展示以下 


....

4,the name is Thread 1;    

0,the name is Thread 2;    

5,the name is Thread 1;    

....

9,the name is Thread 1;    

10,the name is Thread 1;    

1,the name is Thread 2;    

2,the name is Thread 2

      线程1和2交替在终端打印,但是如果我们添加互斥量(相当于是对终端访问的互斥量)之后会出现什么情况呢?

我们修改MyThread.cpp文件如下


#include <string>

#include <stdio.h>

#include <boost/thread/thread.hpp>

#include "MyThread.h"



pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;//添加互斥量



void* MyThread::run() 

{

    pthread_mutex_lock(&mutex);  //加锁

    int sum = this->mCount*10;

    for(int i = 0;i < sum ;i++)

    {

        printf("%2d,the name is %s;\t\n",i,this->mName.c_str());

    }

    pthread_mutex_unlock(&mutex);  //解锁

}



int MyThread::setCount(const int n)

{

    this->mCount = n;

    return 0;

}



int MyThread::setName(const char* aName)

{

    std::string aString(aName);

    this->mName = aString;

    return 0;

我们可以运行一下看下打印信息,没有数据的冲突,因为数据量太大,在此不列出。

 

      C++封装的概念使不同对象之间的私有数据不会交错,这个概念是我这个从C转向C++一直无法理解,尤其是在遇见多线程的情况下,但是这并不表明私有数据不需要加锁,因为可能涉及到类中不同的方法在同时访问或者修改数据。看下面的例子

      我们将main.cpp文件修改如下, 


#include <stdio.h>

#include "MyThread.h"







int main()

{



    MyThread t1(150,"Thread 1");

    //MyThread t2(12,"Thread 2");

    

    t1.start();

    t1.setCount(12);

    //t2.start();

    

    sleep(1);



    return 0;

      将MyThread.cpp文件中的run函数也略作修改


#include <string>

#include <stdio.h>

#include <boost/thread/thread.hpp>

#include "MyThread.h"



void* MyThread::run() 

{

    for(int i = 0;i < this->mCount*10000 ;i++)

    {

        printf("%2d,the name is %s;\t\n",i,this->mName.c_str());

    }

}



int MyThread::setCount(const int n)

{

    this->mCount = n;

    return 0;

}



int MyThread::setName(const char* aName)

{

    std::string aString(aName);

    this->mName = aString;

    return 0;

   大家可以看下运行结果,在这里就不作详细说明;

      为了解决上述的冲突,我们需要在类中添加锁,为了我们修改MyThread.h MyThread.cpp 和 main.cpp函数

MyThread.h文件    


#ifndef MYTHREAD_H

#define MYTHREAD_H



#include <string>

#include "Thread.h"





class MyThread:public Thread

{

public:

    MyThread(const int n,const char* aName):mCount(n),mName(aName)

    {

        pthread_mutex_init(&mutex,NULL);

    }

    virtual void* run();



    int setCount(const int n);



    int setName(const char* aName);



private:

    int mCount;

    std::string mName;

    pthread_mutex_t mutex;

};

MyThread.cpp文件


#include <string>

#include <stdio.h>

#include <boost/thread/thread.hpp>

#include "MyThread.h"



void* MyThread::run() 

{

    pthread_mutex_lock(&mutex);

    //int sum = this->mCount*10;

    for(int i = 0;i < this->mCount*10000 ;i++)

    {

        printf("%2d,the name is %s;\t\n",i,this->mName.c_str());

    }

    pthread_mutex_unlock(&mutex);

}



int MyThread::setCount(const int n)

{

    pthread_mutex_lock(&mutex);

    this->mCount = n;

    pthread_mutex_unlock(&mutex);

    return 0;

}



int MyThread::setName(const char* aName)

{

    std::string aString(aName);

    this->mName = aString;

    return 0;

main.cpp 文件


#include <stdio.h>

#include "MyThread.h"







int main()

{



    MyThread t1(150,"Thread 1");

    

    t1.start();

    sleep(1);

    t1.setCount(12);

    t1.start();

    



    return 0;

 

       有兴趣的读者可以看下运行效果,在添加了类内部锁之后,有效的实现了数据的同步。

       欢迎讨论。 

相关文章
|
1月前
|
Java
如何在Java中进行多线程编程
Java多线程编程常用方式包括:继承Thread类、实现Runnable接口、Callable接口(可返回结果)及使用线程池。推荐线程池以提升性能,避免频繁创建线程。结合同步与通信机制,可有效管理并发任务。
139 6
|
4月前
|
Java API 微服务
为什么虚拟线程将改变Java并发编程?
为什么虚拟线程将改变Java并发编程?
296 83
|
27天前
|
Java 调度 数据库
Python threading模块:多线程编程的实战指南
本文深入讲解Python多线程编程,涵盖threading模块的核心用法:线程创建、生命周期、同步机制(锁、信号量、条件变量)、线程通信(队列)、守护线程与线程池应用。结合实战案例,如多线程下载器,帮助开发者提升程序并发性能,适用于I/O密集型任务处理。
201 0
|
2月前
|
算法 Java
Java多线程编程:实现线程间数据共享机制
以上就是Java中几种主要处理多线程序列化资源以及协调各自独立运行但需相互配合以完成任务threads 的技术手段与策略。正确应用上述技术将大大增强你程序稳定性与效率同时也降低bug出现率因此深刻理解每项技术背后理论至关重要.
207 16
|
6月前
|
机器学习/深度学习 消息中间件 存储
【高薪程序员必看】万字长文拆解Java并发编程!(9-2):并发工具-线程池
🌟 ​大家好,我是摘星!​ 🌟今天为大家带来的是并发编程中的强力并发工具-线程池,废话不多说让我们直接开始。
238 0
|
9月前
|
存储 缓存 C++
C++ 容器全面剖析:掌握 STL 的奥秘,从入门到高效编程
C++ 标准模板库(STL)提供了一组功能强大的容器类,用于存储和操作数据集合。不同的容器具有独特的特性和应用场景,因此选择合适的容器对于程序的性能和代码的可读性至关重要。对于刚接触 C++ 的开发者来说,了解这些容器的基础知识以及它们的特点是迈向高效编程的重要一步。本文将详细介绍 C++ 常用的容器,包括序列容器(`std::vector`、`std::array`、`std::list`、`std::deque`)、关联容器(`std::set`、`std::map`)和无序容器(`std::unordered_set`、`std::unordered_map`),全面解析它们的特点、用法
C++ 容器全面剖析:掌握 STL 的奥秘,从入门到高效编程
|
9月前
|
Linux
Linux编程: 在业务线程中注册和处理Linux信号
通过本文,您可以了解如何在业务线程中注册和处理Linux信号。正确处理信号可以提高程序的健壮性和稳定性。希望这些内容能帮助您更好地理解和应用Linux信号处理机制。
166 26
|
9月前
|
Linux
Linux编程: 在业务线程中注册和处理Linux信号
本文详细介绍了如何在Linux中通过在业务线程中注册和处理信号。我们讨论了信号的基本概念,并通过完整的代码示例展示了在业务线程中注册和处理信号的方法。通过正确地使用信号处理机制,可以提高程序的健壮性和响应能力。希望本文能帮助您更好地理解和应用Linux信号处理,提高开发效率和代码质量。
177 17
|
9月前
|
存储 机器学习/深度学习 编译器
【C++终极篇】C++11:编程新纪元的神秘力量揭秘
【C++终极篇】C++11:编程新纪元的神秘力量揭秘
|
9月前
|
存储 算法 C++
深入浅出 C++ STL:解锁高效编程的秘密武器
C++ 标准模板库(STL)是现代 C++ 的核心部分之一,为开发者提供了丰富的预定义数据结构和算法,极大地提升了编程效率和代码的可读性。理解和掌握 STL 对于 C++ 开发者来说至关重要。以下是对 STL 的详细介绍,涵盖其基础知识、发展历史、核心组件、重要性和学习方法。

热门文章

最新文章