C++在linux下怎么多线程

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++在linux下怎么多线程相关的知识,希望对你有一定的参考价值。

求示例
请用//代码段 表示

#ifndef THREAD_H_  
#define THREAD_H_  
#include <unistd.h>  
#include <pthread.h>  
class Runnable  
  
public:  
//运行实体  
virtual void run() = 0;  
;  
//线程类  
class Thread: public Runnable  
  
private:  
//线程初始化号  
static int thread_init_number;  
//当前线程初始化序号  
int current_thread_init_number;  
//线程体  
Runnable *target;  
//当前线程的线程ID  
pthread_t tid;  
//线程的状态  
int thread_status;  
//线程属性  
pthread_attr_t attr;  
//线程优先级  
sched_param param;  
//获取执行方法的指针  
static void* run0(void* pVoid);  
//内部执行方法  
void* run1();  
//获取线程序号  
static int get_next_thread_num();  
public:  
//线程的状态-新建  
static const int THREAD_STATUS_NEW = 0;  
//线程的状态-正在运行  
static const int THREAD_STATUS_RUNNING = 1;  
//线程的状态-运行结束  
static const int THREAD_STATUS_EXIT = -1;  
//构造函数  
Thread();  
//构造函数  
Thread(Runnable *target);  
//析构  
~Thread();  
//线程的运行体  
void run();  
//开始执行线程  
bool start();  
//获取线程状态  
int get_state();  
//等待线程直至退出  
void join();  
//等待线程退出或者超时  
void join(unsigned long millis_time);  
//比较两个线程时候相同,通过current_thread_init_number判断  
bool operator ==(const Thread* other_pthread);  
//获取this线程ID  
pthread_t get_thread_id();  
//获取当前线程ID  
static pthread_t get_current_thread_id();  
//当前线程是否和某个线程相等,通过tid判断  
static bool is_equals(Thread* iTarget);  
//设置线程的类型:绑定/非绑定  
void set_thread_scope(bool isSystem);  
//获取线程的类型:绑定/非绑定  
bool get_thread_scope();  
//设置线程的优先级,1-99,其中99为实时,意外的为普通  
void set_thread_priority(int priority);  
//获取线程的优先级  
int get_thread_priority();  
;  
int Thread::thread_init_number = 1;  
inline int Thread::get_next_thread_num()  
  
return thread_init_number++;  
  
void* Thread::run0(void* pVoid)  
  
Thread* p = (Thread*) pVoid;  
p->run1();  
return p;  
  
void* Thread::run1()  
  
thread_status = THREAD_STATUS_RUNNING;  
tid = pthread_self();  
run();  
thread_status = THREAD_STATUS_EXIT;  
tid = 0;  
pthread_exit(NULL);  
  
void Thread::run()  
  
if (target != NULL)  
  
  (*target).run();  
  
  
Thread::Thread()  
  
tid = 0;  
thread_status = THREAD_STATUS_NEW;  
current_thread_init_number = get_next_thread_num();  
pthread_attr_init(&attr);  
  
Thread::Thread(Runnable *iTarget)  
  
target = iTarget;  
tid = 0;  
thread_status = THREAD_STATUS_NEW;  
current_thread_init_number = get_next_thread_num();  
pthread_attr_init(&attr);  
  
Thread::~Thread()  
  
pthread_attr_destroy(&attr);  
  
bool Thread::start()  
  
return pthread_create(&tid, &attr, run0, this);  
  
inline pthread_t Thread::get_current_thread_id()  
  
return pthread_self();  
  
inline pthread_t Thread::get_thread_id()  
  
return tid;  
  
inline int Thread::get_state()  
  
return thread_status;  
  
void Thread::join()  
  
if (tid > 0)  
  
  pthread_join(tid,NULL);  
  
  
void Thread::join(unsigned long millis_time)  
  
if (tid == 0)  
  
  return;  
  
if (millis_time == 0)  
  
  join();  
  
else  
  
  unsigned long k = 0;  
  while (thread_status != THREAD_STATUS_EXIT && k <= millis_time)  
    
   usleep(100);  
   k++;  
    
  
  
bool Thread::operator ==(const Thread* other_pthread)  
  
if(other_pthread==NULL)  
  
  return false;  
if(current_thread_init_number==(*other_pthread).current_thread_init_number)  
  
  return true;  
  
return false;  
  
bool Thread::is_equals(Thread* iTarget)  
  
if (iTarget == NULL)  
  
  return false;  
  
return pthread_self() == iTarget->tid;  
  
void Thread::set_thread_scope(bool isSystem)  
  
if (isSystem)  
  
  pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);  
  
else  
  
  pthread_attr_setscope(&attr, PTHREAD_SCOPE_PROCESS);  
  
  
void Thread::set_thread_priority(int priority)  
  
pthread_attr_getschedparam(&attr,&param);  
param.__sched_priority = priority;  
pthread_attr_setschedparam(&attr,&param);  
  
int Thread::get_thread_priority()  
pthread_attr_getschedparam(&attr,&param);  
return param.__sched_priority;  
  
#endif /* THREAD_H_ */

参考技术A 与c语言一样,使用线程库,pthread线程,例如
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
struct member

int num;
char *name;
;

//结构体后的分号勿漏

void *create(void *arg)

//有void* 型参数传入,不能直接void


struct member *temp;
temp=(struct member *)arg;

//结构体变量之间不能直接赋值,但可以通过指针赋地址

printf("member->num:%d\n",temp->num);
printf("member->name:%s\n",temp->name);
sleep(1);
return (void *)8;

//这个很有特色,返回一个指向void的数据类型的值,这个值作为后面的exit code


int main(int agrc,char* argv[])

pthread_t tidp;
struct member *b;
void* a;
b=(struct member *)malloc(sizeof(struct member));

//先分配内存空间撒~

b->num=1;
b->name="mlq";

//字符串赋值,其他好用简便的方法有: char *p = NULL; p = new char [256];

if((pthread_create(&tidp,NULL,create,(void*)b))==-1) /

//

void *

为“无类型指针”,void * 可以指向任何类型的数据


printf("create error!\n");
return 1;

if(pthread_join(tidp,&a))
//调用
pthread_join函数,等待线程结束再继续往下执行,要不然主进程和下面的线程并行执行


printf("thread is not exit...\n");
return -2;

printf("thread is exit ,code is %d\n",(int)a); //不知为啥这里是(int)a,,a不是指针来的么
return 0;
本回答被提问者和网友采纳

Linux C++多线程同步的四种方式

参考技术A From : https://blog.csdn.net/qq_39382769/article/details/96075346

1.同一个线程内部,指令按照先后顺序执行;但不同线程之间的指令很难说清楚是哪一个先执行,在并发情况下,指令执行的先后顺序由内核决定。

如果运行的结果依赖于不同线程执行的先后的话,那么就会形成竞争条件,在这样的情况下,计算的结果很难预知,所以应该尽量避免竞争条件的形成。

2.最常见的解决竞争条件的方法是:将原先分离的两个指令构成一个不可分割的原子操作,而其他任务不能插入到原子操作中!

3.对多线程来说,同步指的是在一定时间内只允许某一个线程访问某个资源,而在此时间内,不允许其他线程访问该资源!

互斥锁
条件变量
读写锁
信号量

一种特殊的全局变量,拥有lock和unlock两种状态。
unlock的互斥锁可以由某个线程获得,一旦获得,这个互斥锁会锁上变成lock状态,此后只有该线程由权力打开该锁,其他线程想要获得互斥锁,必须得到互斥锁再次被打开之后。

1.互斥锁的初始化, 分为静态初始化和动态初始化.

2.互斥锁的相关属性及分类

(1) attr表示互斥锁的属性;

(2) pshared表示互斥锁的共享属性,由两种取值:

1)PTHREAD_PROCESS_PRIVATE:锁只能用于一个进程内部的两个线程进行互斥(默认情况)

2)PTHREAD_PROCESS_SHARED:锁可用于两个不同进程中的线程进行互斥,使用时还需要在进程共享内存中分配互斥锁,然后为该互斥锁指定属性就可以了。

互斥锁存在缺点:
(1)某个线程正在等待共享数据内某个条件出现。

(2)重复对数据对象加锁和解锁(轮询),但是这样轮询非常耗费时间和资源,而且效率非常低,所以互斥锁不太适合这种情况。

当线程在等待满足某些条件时,使线程进入睡眠状态;一旦条件满足,就换线因等待满足特定条件而睡眠的线程。
程序的效率无疑会大大提高。

1)创建

静态方式:pthread_cond_t cond PTHREAD_COND_INITIALIZER

动态方式:int pthread_cond_init(&cond,NULL)

Linux thread 实现的条件变量不支持属性,所以NULL(cond_attr参数)

2)注销

int pthread_cond_destory(&cond)

只有没有线程在该条件变量上,该条件变量才能注销,否则返回EBUSY

因为Linux实现的条件变量没有分配什么资源,所以注销动作只包括检查是否有等待线程!(请参考条件变量的底层实现)

3)等待

条件等待:int pthread_cond_wait(&cond,&mutex)

计时等待:int pthread_cond_timewait(&cond,&mutex,time)

1.其中计时等待如果在给定时刻前条件没有被满足,则返回ETIMEOUT,结束等待

2.无论那种等待方式,都必须有一个互斥锁配合,以防止多个线程同时请求pthread_cond_wait形成竞争条件!

3.在调用pthread_cond_wait前必须由本线程加锁

4)激发

激发一个等待线程:pthread_cond_signal(&cond)

激发所有等待线程:pthread_cond_broadcast(&cond)

重要的是,pthread_cond_signal不会存在惊群效应,也就是是它最多给一个等待线程发信号,不会给所有线程发信号唤醒,然后要求他们自己去争抢资源!

pthread_cond_broadcast() 唤醒所有正在pthread_cond_wait()的同一个条件变量的线程。注意:如果等待的多个现场不使用同一个锁,被唤醒的多个线程执行是并发的。

pthread_cond_broadcast & pthread_cond_signal

1.读写锁比互斥锁更加具有适用性和并行性

2.读写锁最适用于对数据结构的读操作读操作次数多余写操作次数的场合!

3.锁处于读模式时可以线程共享,而锁处于写模式时只能独占,所以读写锁又叫做共享-独占锁。

4.读写锁有两种策略:强读同步和强写同步

强读同步:
总是给读者更高的优先权,只要写者没有进行写操作,读者就可以获得访问权限

强写同步:
总是给写者更高的优先权,读者只能等到所有正在等待或者执行的写者完成后才能进行读

1)初始化的销毁读写锁

静态初始化:pthread_rwlock_t rwlock=PTHREAD_RWLOCK_INITIALIZER

动态初始化:int pthread_rwlock_init(rwlock,NULL),NULL代表读写锁采用默认属性

销毁读写锁:int pthread_rwlock_destory(rwlock)

在释放某个读写锁的资源之前,需要先通过pthread_rwlock_destory函数对读写锁进行清理。释放由pthread_rwlock_init函数分配的资源

如果你想要读写锁使用非默认属性,则attr不能为NULL,得给attr赋值

int pthread_rwlockattr_init(attr),给attr初始化

int pthread_rwlockattr_destory(attr),销毁attr

2)以写的方式获取锁,以读的方式获取锁,释放读写锁

int pthread_rwlock_rdlock(rwlock),以读的方式获取锁

int pthread_rwlock_wrlock(rwlock),以写的方式获取锁

int pthread_rwlock_unlock(rwlock),释放锁

上面两个获取锁的方式都是阻塞的函数,也就是说获取不到锁的话,调用线程不是立即返回,而是阻塞执行,在需要进行写操作的时候,这种阻塞式获取锁的方式是非常不好的,你想一下,我需要进行写操作,不但没有获取到锁,我还一直在这里等待,大大拖累效率

所以我们应该采用非阻塞的方式获取锁:

int pthread_rwlock_tryrdlock(rwlock)

int pthread_rwlock_trywrlock(rwlock)

互斥锁只允许一个线程进入临界区,而信号量允许多个线程进入临界区。

1)信号量初始化
int sem_init(&sem,pshared, v)
pshared为0,表示这个信号量是当前进程的局部信号量。
pshared为1,表示这个信号量可以在多个进程之间共享。
v为信号量的初始值。

返回值:
成功:0,失败:-1

2)信号量值的加减
int sem_wait(&sem):以原子操作的方式将信号量的值减去1

int sem_post(&sem):以原子操作的方式将信号量的值加上1

3)对信号量进行清理

int sem_destory(&sem)

以上是关于C++在linux下怎么多线程的主要内容,如果未能解决你的问题,请参考以下文章

Linux C++多线程同步的四种方式

C++多线程怎么实现

Linux C++的多线程编程

Linux多线程服务端编程:使用muduo C++网络库

c++ 求助socket多线程网络通信怎么实现并发

在C++中使用openmp进行多线程编程