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;
有兴趣的读者可以看下运行效果,在添加了类内部锁之后,有效的实现了数据的同步。
欢迎讨论。