0%

线程

线程

线程

线程创建

1
2
3
4
5
6
7
8
9
10
11
12
#include<pthread.h>
int pthread_creat( //创建线程,成功返回0,失败返回errcode
pthread_t *thread, //线程号
pthread_attr_t *attr, //
void *(*func)(void*), //线程需要运行的函数
void *arg //传递给func的参数
)

int pthread_join( //等待线程终止,成功返回0,失败返回errcode
pthread_t pthread, //所等待的线程号
void* retval //指向线程返回值
)

在linux中使用pthread.h头文件需要连接lpthread库

线程池

组成成分

  1. 线程池管理器
  2. 工作线程
  3. 任务接口
  4. 任务队列

工作流程

1
2
3
4
5
6
7
1. 初始化线程池
2. 堵塞任务线程
2. 将任务添加进人物队列
3. 判断是否有空闲线程
4. 唤醒线程
5. 完成任务
6. 重新堵塞线程

常见线程池

  • 单线程池

    每次只有一个线程工作

  • 固定线程池

    线程池中线程的数量固定,当达到线程池最大数量时,后续任务进入等待队列

  • 可缓存线程池

    当任务超出线程数量时,添加线程,当线程池空闲线程数量过多时,回收部分空间

  • 无限制线程池

    线程池大小无限制,支持定时和周期性执行

优点

1
2
3
1. 控制线程产生数量,控制线程对象的内存消耗
2. 降低系统开销和资源消耗
3. 提高系统响应速度

通信

线程

进程

  • 命名通道 1. 通道是一个队列而不是常规文件 2. 其读和写是原子操作
  • 共享内存 1. 共享内存段不依赖于进程存在 2. 共享内存段的名字叫关键字 3. 关键字是一个整型数 4. 共享内存段有自己的拥有者己权限位 5. 进程可以连接共享内存段,并获得指针
  • 文件锁
  • 信号量
  • 相关函数 1. select、poll 2. mkfio 3. shmget、shmat、shmctl、shmdt(共享内存) 4.semget、semctl、semop

同步

互斥量

1
2
3
4
5
6
7
8
#include <pthread.h>
int pthread_mutex_lock( //等待互斥锁解开后锁住互斥量,成功返回0
pthread_mutex_t *mutex //指向互斥锁
)

int pthread_mutex_unlock( //解锁互斥量,成功返回0
pthread_mutex_t *mutex, //指向互斥量
)

条件变量

1
2
3
4
5
6
7
8
#include <pthread.h>
int pthread_cond_wait( //挂起线程,等待信号量,成功返回0
pthread_cond_t *cond, //
pthread_mutex_t *mutex, //指向互斥锁对象
)

int pthread_cond_signal( //唤醒等待线程,成功返回0
pthread_cond_t *cond) //指向条件变量

pthread_cond函数总是和互斥锁在一起使用。此函数先自动释放指定的锁,然后等待条件变量的变化。如果在调用此函数之前,互斥量mutex并没有被锁住,函数执行的结果是不确定的。在返回原调用函数之前,此函数自动将指定的互斥量重新锁住。

信号量

1
2
3
4
5
6
#include <semaphore.h>
int sem_init(sem_t *sem, //sem地址
int pshared, //0表示本进程中多个线程间同步,非0表示可以跨进程的同步操作
unsigned int value); //信号量初值(计数器的值)
P int sem_wait(sem_t *sem); // sem-1 如果小于0就阻塞
V int sem_post(sem_t *sem); // sem+1

读写锁

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//初始化和销毁
#include <pthread.h>
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr);
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
// 成功则返回0, 出错则返回错误编号.

int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
// 成功则返回0, 出错则返回错误编号.

int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
// 成功则返回0, 出错则返回错误编号.

安全

在多线程程序中,很有可能会将同一个文件描述符传递给两个不同的线程。即传递给它们的两个值指向同一个文件描述符。显然如果一个线程中的函数关闭了这个文件,此文件描述符对此进程中的任何线程来说都已经被关闭。

fork创建了一个新的进程,并把原调用进程的数据和代码复制给这个新的进程。如果线程中的某函数调用了 fork,只有调用fork的线程在新的进程中运行

总结

-[ ] select和epoll