1.线程是什么
在一个程序里的一个执行路线叫做线程(thread),线程是“一个进程内部的控制序列”
2.线程和进程的区别
进程是操作系统分配资源的基本单位
线程是CPU调度的基本单位
-
线程的优缺点
线程的优点:
1.创建一个新线程的代价要比创建一个新进程小得多
2.与进程之间的切换相比,线程之间的切换需要操作系统做的操作要少很多
3.线程占用的资源要比进程少很多
4.能充分利用多处理器的可并行数量
5.在等待慢速I/O操作结束的同时,程序可执行其他的计算任务
6.计算密集型应用,为了能在多处理器系统上运行,将计算分解到多个线程中实现
7.I/O密集型应用,为了提高性能,将I/O操作重叠。线程可以同时等待不同的I/O操作。
线程缺点:
1.性能损失
2.健壮性降低
3.缺乏访问控制
4.编程难度提高
3.线程控制
线程的创建
原型
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*star
t_routine)(void*), void *arg);
参数
thread:返回线程ID
attr:设置线程的属性,attr为NULL表示使用默认属性
start_routine:是个函数地址,线程启动后要执行的函数
arg:传给线程启动函数的参数
返回值:成功返回0;失败返回错误码
线程终止
原型
void pthread_exit(void *value_ptr);
参数
value_ptr:value_ptr不要指向一个局部变量。
返回值:无返回值,跟进程一样,线程结束的时候无法返回到它的调用者(自身)
线程等待与分离
原型
int pthread_join(pthread_t thread, void **value_ptr);
参数
thread:线程ID
value_ptr:它指向一个指针,后者指向线程的返回值
返回值:成功返回0,失败返回错误码
4.同步与互斥
(1)互斥量(mutex)
初始化:
1.静态分配
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER
2.动态分配
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr
_t *restrict attr);
参数:
mutex:要初始化的互斥量
attr:NULL
销毁互斥量
int pthread_mutex_destroy(pthread_mutex_t *mutex);
互斥量加锁与解锁
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
返回值:成功返回0,失败返回错误号
(2)四个死锁的必要条件
- 互斥条件
- 不可剥夺条件
- 请求与保持条件
- 环路等待条件
(3)条件变量函数
1.初始化
int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *rest
rict attr);
参数:
cond:要初始化的条件变量
attr:NULL
2.销毁
int pthread_cond_destroy(pthread_cond_t *cond)
3.等待条件满足
int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mute
x);
参数:
cond:要在这个条件变量上等待
mutex:互斥量
4.唤醒等待
int pthread_cond_broadcast(pthread_cond_t *cond);
int pthread_cond_signal(pthread_cond_t *cond);
(4)生产者与消费者模型
#include<stdio.h>
2 #include<stdlib.h>
3 #include<unistd.h>
4 //条件变量函数
5 //pthread_cond_init 初始化
6 //pthread_cond_destroy 销毁
7 //pthread_cond_wait 等待
8 //pthread_cond_signal 唤醒等待
9
10 int noodles=0;
11 pthread_cond_t cond;
12 pthread_mutex_t mutex;
13
14 void *thr_producer(void*arg)
15 {
16 int id=(int)arg;
17 while(1)
18 {
19 pthread_mutex_lock(&mutex);//加锁
20 while(noodles==1)
21 {
22 pthread_cond_wait(&cond,&mutex);//等待
23 }
24 printf("producer:%d on sale!!\n",id);
25 noodles=1;
26 //悄悄告诉别人,面条生产出来了
27 pthread_cond_signal(&cond);//唤醒等待
28 pthread_mutex_unlock(&mutex);//解锁
29 }
30 return NULL;
31 }
32
33 void *thr_consumer(void *arg)
34 {
35 int id=(int)arg;
36 while(1)
37 {
38 pthread_mutex_lock(&mutex);
39 while(noodles==0)//如果没有面条就等待
40 {
41 pthread_cond_wait(&cond,&mutex);
42 }
43 printf("consumer:%d oh my god!!!\n",id);
44 noodles=0;
45 pthread_cond_signal(&cond);//唤醒等待
46 pthread_mutex_unlock(&mutex);//解锁
47 }
48 return NULL;
49 }
50
51 int main()
52 {
53 pthread_t tid1,tid2;
54 int ret,i;
55 pthread_cond_init(&cond,NULL);//初始化条件变量函数
56 pthread_mutex_init(&mutex,NULL);//初始化互斥量
57 for(i=0;i<4;i++)
58 {
59 ret=pthread_create(&tid1,NULL,thr_producer,(void* )i);//创建线程
60 if(ret!=0)
61 {
62 printf("pthread_create error!!\n");
63 return -1;
64 }
65 }
66 for(i=0;i<4;i++)
67 {
68 ret=pthread_create(&tid2,NULL,thr_producer,(void*)i);//创
建线程
69 if(ret!=0)
70 {
71 printf("pthread_create error!!\n");
72 return -1;
73 }
74 }
75 pthread_join(tid1,NULL);//等待线程结束
76 pthread_join(tid2,NULL);
77 pthread_cond_destroy(&cond);//销毁
78 pthread_mutex_destroy(&mutex);
79 return 0;
80 }
(5)POSIX信号量
1.初始化信号量
#include <semaphore.h>
int sem_init(sem_t *sem, int pshared, unsigned int value);
参数:
pshared:0表示线程间共享,非零表示进程间共享
value:信号量初始值
2.销毁信号量
int sem_destroy(sem_t *sem);
3.等待信号量
功能:等待信号量,会将信号量的值减1
int sem_wait(sem_t *sem);
4.布信号量
功能:发布信号量,表示资源使用完毕,可以归还资源了。将信号量值加1。
int sem_post(sem_t *sem);
(6)读写锁
1.初始化
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock,const pthread_rwlockattr
_t *restrict attr);
2.销毁
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
3.加锁和解锁
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);