#include <pthread.h>
#include <QDebug>
void *working(void *arg)
{
qDebug()<<"我是子线程1,线程id:"<<pthread_self()<<"\n";
for(int i=0;i<9;i++)
{
qDebug()<<"子线程1:"<<i<<"\n";
}
return nullptr;
}
void *working2(void *arg)
{
qDebug()<<"我是子线程2,线程id:"<<pthread_self()<<"\n";
for(int i=0;i<22;i++)
{
qDebug()<<"子线程2:"<<i<<"\n";
}
return nullptr;
}
int main()
{
//返回当前线程id
pthread_t id_parent = pthread_self();
qDebug()<<"主线程id:"<<id_parent<<"\n";
//创建子线程,第二个参数是线程的属性
pthread_t tid_children;
pthread_create(&tid_children,NULL,working,NULL);
qDebug()<<"子线程1id:"<<tid_children<<"\n";
//
//创建子线程
pthread_t tid_children2;
pthread_create(&tid_children2,NULL,working2,NULL);
qDebug()<<"子线程2id:"<<tid_children2<<"\n";
//主线程执行代码
qDebug()<<"我是主线程,id:"<<pthread_self()<<"\n";
for(int i=10;i<20;i++)
{
qDebug()<<"主线程:"<<i<<"\n";
}
//线程退出不会影像其他线程,主线程一样,参数是退出时携带的数据,由该线程的主线程接收
pthread_exit(NULL);
//当一个线程处于join状态,无论线程使用phtread_exit还是return返回结果,终止线程所占用的资源不会随着线程的结束而归还系统,而是仍为线程所在进程持有
//因此在默认情况下,一个线程被创建后,必须使用pthread_join对创建线程进行资源回收
return 0;
}
(1)pthread_exit相当于函数的return,退出线程对其他线程没有影响,也可以用来传值给主线程(这里把创建其他线程的线程称为主线程);
(2)线程必须用pthread_join或者pthread_detach来回收线程本身所占用的资源;
#include <pthread.h>
#include <QDebug>
void *working(void *arg)
{
int *p=(int *)arg;
*p =3;
pthread_exit(p);
return nullptr;
}
int main()
{
int p=2;
pthread_t children_thread;
qDebug()<<"p:"<<p<<"\n";
int ret = pthread_create(&children_thread,NULL,working,&p);
if(ret ==0)
{
qDebug()<<"create success\n";
}
else
{
qDebug()<<"create fail\n";
}
void *ptr=NULL;
//修改ptr指针指向pthread_exit参数指向的内存,ptr指针与pthread_exit参数指向同一块内存
//所以传入ptr指针地址,用于修改
pthread_join(children_thread,&ptr);
int *res = (int *)ptr;
qDebug()<<"p:"<<p<<"\n";
qDebug()<<"res:"<<*res<<"\n";
return 0;
}
(1)线程的返回值用pthread_exit,接收参数的线程用pthread_join;
(2)可以用主线程的内存,使用pthread_create来传参;
#include<iostream>
#include<pthread.h>
#include<QDebug>
using namespace std;
#define MAX 10
int number=0;
pthread_mutex_t m_mutex= PTHREAD_MUTEX_INITIALIZER;
void *funA(void *arg)
{
for(int i=0;i<MAX;i++)
{
//pthread_mutex_lock(&m_mutex);
int ret = pthread_mutex_trylock(&m_mutex);
if(ret!=0)
{
qDebug()<<"mutex is not avaliable";
}
else
{
if(i==5)
{
break;
}
qDebug()<<"funA-before:"<<number;
int cur=number;
cur++;
number=cur;
qDebug()<<"funA-after:"<<number;
pthread_mutex_unlock(&m_mutex);
}
//只有锁里面的是正常结果,下面这条qDebug在锁外面,有可能执行到这条语句之前时间片被funB抢走
//所以本来应该显示正常结果,会显示funB运行完后的结果
//qDebug()<<"funA:"<<number;
}
return NULL;
}
void *funB(void *arg)
{
for(int i=0;i<MAX;i++)
{
//pthread_mutex_lock(&m_mutex);
int ret = pthread_mutex_trylock(&m_mutex);
if(ret!=0)
{
qDebug()<<"mutex is not avaliable";
}
else
{
qDebug()<<"funB-before:"<<number;
int cur=number;
cur++;
number=cur;
qDebug()<<"funB-after:"<<number;
pthread_mutex_unlock(&m_mutex);
}
//qDebug()<<"funB:"<<number;
}
return NULL;
}
int main(int argc,char **argv)
{
//pthread_mutex_init(&m_mutex,NULL);
pthread_t p1,p2;
pthread_create(&p1,NULL,funA,NULL);
pthread_create(&p2,NULL,funB,NULL);
pthread_join(p1,NULL);
pthread_join(p2,NULL);
qDebug()<<"here";
pthread_mutex_destroy(&m_mutex);
return 0;
}
(1)使用pthread_mutex_lock时会出现死锁的问题,如果funA突然break,锁没有解开,funB会一直阻塞,pthread_mutex_lock等不到锁会一直阻塞,所以使用pthread_mutex_trylock代替,如果拿不到锁会直接返回非0的值;
(2)还可以使用pthread_mutex_timedlock定时解锁函数;
(3)在c++线程函数中有std::lock_guard和std::unique_lock函数,两者都可以预防以上死锁情况,std::lock_guard出了定义域就可以解锁,里面的设计非常巧妙,该类在构造函数中加锁,在析构函数中解锁。unique_lock相比于lock_guard提供了更多接口,但性能不如lock_guard;
(4)c++线程库相比于Linux线程库会少很多功能,因此还是建议使用linux线程函数;