Linux高性能服务器编程第十四章多线程编程

本章内容包括:

  • 创建线程和结束线程
  • 读取和设置线程属性
  • 同步方式:信号量、互斥锁和条件变量

创建线程和结束线程

pthread_create

创建线程所使用的函数:

1
2
#include <pthread.h>
int pthread_create ( pthread_t* thread,const pthread_attr_t* attr,void*〔*start_routine) ( void* ) , void* arg );
  • thread参数是新线程的标识符,后续pthread_*通过它来引用新线程,是一个整型类型
  • attr参数设置新线程的属性,给他传递NULL表示使用默认线程属性
  • 后面两个参数分别表示指定新线程将运行的函数及其参数

pthread_exit

1
2
include <pthread.h>
void pthread_exit ( void* retval ) ;

pthread_join

一个进程的所有线程都可以调用这个函数去回收其他线程

1
2
#include <pthread.h>
int pthread_join ( pthread_t thread,void* *retval );

thread是目标线程的标识符

信号量

信号量函数的名字都以sem_开头:

image-20231112195112215

互斥锁

基础API

image-20231112194932118

互斥锁属性

image-20231112194901127

条件变量

image-20231112195348731

包装类例程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//sem
class sem
{
public:
sem(){
if(sem_init(m_sem,0,0)!=0)
throw std::exception();
}
~sem(){
sem_destroy(&m_sem);
}
bool wait(){
return sem_wait(&m_sem)==0;
}
bool post(){
return sem_post(&m_sem)==0;
}
private:
sem_t m_sem;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//locker
class locker
{
public:
locker(){
if(pthread_mutex_init(&m_mutex,NULL)!=0){
throw std::exception();
}
}
~locker(){
pthread_mutex_destroy(&m_mutex);
}
bool lock(){
return pthread_mutex_lock(&m_mutex)==0;
}
bool unlock(){
return pthread_mutex_unlock(&m_mutex)==0;
}
private:
pthread_mutex_t m_mutex;
}
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
//conditon
class condition(){
public:
cond(){
if(pthread_mutex_init(&m_mutex,NULL)!=0)
throw std::exception();
if(pthread_cond_init(&m_cond,NULL)!=0){
pthread_mutex_destroy(&m_mutex);
throw std::exception();
}
}
~cond(){
pthread_mutex_destroy(&m_mutex);
pthread_cond_destroy(&m_cond);
}
bool wait(){
int ret = 0 ;
pthread_mutex_lock ( &m_mutex ) ;
ret = pthread_cond_wait (&m_cond,&m_mutex );
pthread_mutex_unlock (&m_mutex);
return ret == 0 ;
}
bool signal(){
return pthread_cond_signal(&m_cond)==0
}
private:
pthread_mutex_t m_mutex;
pthread_cond_t m_cond;
}

多线程环境

  • 可重入函数

    有一部分函数不能被多个线程调用且不发生竞态条件

  • 线程和进程

    如果一个多线程程序的一个线程调用了fork函数,那么子进程不会创建相同数量的线程,子进程会自动调用互斥锁的状态

  • 线程和信号

    每个线程都可以独立地设置信号掩码