1.线程的分离属性:
线程在结束时由操作系统自动回收线程空间
pthread_attr_init
int pthread_attr_init(pthread_attr_t *attr);
功能:
初始化线程属性
pthread_attr_destroy
int pthread_attr_destroy(pthread_attr_t *attr);
功能:
销毁线程属性
pthread_attr_setdetachstate
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
功能:
将线程设置为分离属性
参数:
attr:线程属性
detachstate:PTHREAD_CREATE_DETACHED 分离属性
PTHREAD_CREATE_JOINABLE 加入属性(默认)
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 30 31 32 33 34 35 36 37 38 39 40 41 | #include "../head.h" void *thread1fun(void *arg) { printf("线程1(TID:%#lx)开始执行\n", (unsigned long)pthread_self()); return NULL; } void *thread2fun(void *arg) { printf("线程2(TID:%#lx)开始执行\n", (unsigned long)pthread_self()); return NULL; } void *thread3fun(void *arg) { printf("线程3(TID:%#lx)开始执行\n", (unsigned long)pthread_self()); return NULL; } int main(void) { pthread_t tid1; pthread_t tid2; pthread_t tid3; pthread_create(&tid1, NULL, thread1fun, NULL); pthread_create(&tid2, NULL, thread2fun, NULL); pthread_create(&tid3, NULL, thread3fun, NULL); printf("线程(TID:%#lx TID:%#lx TID:%#lx)创建成功\n", (unsigned long)tid1, (unsigned long)tid2, (unsigned long)tid3); pthread_join(tid1, NULL); pthread_join(tid2, NULL); pthread_join(tid3, NULL); return 0; } |
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 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | #include "../head.h" void *thread1fun(void *arg) { printf("线程1(TID:%#lx)开始执行\n", (unsigned long)pthread_self()); return NULL; } void *thread2fun(void *arg) { printf("线程2(TID:%#lx)开始执行\n", (unsigned long)pthread_self()); return NULL; } void *thread3fun(void *arg) { printf("线程3(TID:%#lx)开始执行\n", (unsigned long)pthread_self()); return NULL; } int main(void) { pthread_t tid[3]; int i = 0; void *(*pfun[3])(void *) = {thread1fun, thread2fun, thread3fun}; pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); for (i = 0; i < 3; i++) { pthread_create(&tid[i], &attr, pfun[i], NULL); } printf("线程(TID:%#lx TID:%#lx TID:%#lx)创建成功\n", (unsigned long)tid[0], (unsigned long)tid[1], (unsigned long)tid[2]); while (1) { } #if 0 for (i = 0; i < 3; i++) { pthread_join(tid[i], NULL); } #endif pthread_attr_destroy(&attr); return 0; } |
2.互斥锁:
1.资源:
资源是有限的,在程序运行过程中,一段代码、一段空间、一个变量、CPU、内存都可以看做资源
2.互斥锁:
是一种资源,当一个线程任务加锁,其余线程任务无法再次加锁,直到解锁后才能加锁
互斥锁主要是用来防止多个线程任务竞争某个资源
加锁和解锁中间的代码称为临界代码也称为临界区
3.函数接口:
pthread_mutex_init
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);
功能:
初始化互斥锁
参数:
mutex:互斥锁
attr:互斥锁属性 NULL
返回值:
成功返回0
失败返回-1
pthread_mutex_destroy
int pthread_mutex_destroy(pthread_mutex_t *mutex);
功能:
销毁互斥锁
参数:
mutex:互斥锁
返回值:
成功返回0
失败返回-1
pthread_mutex_lock
int pthread_mutex_lock(pthread_mutex_t *mutex);
功能:
加锁
参数:
mutex:互斥锁
返回值:
成功返回0
失败返回-1
pthread_mutex_unlock
int pthread_mutex_unlock(pthread_mutex_t *mutex);
功能:
解锁
参数:
mutex:互斥锁
返回值:
成功返回0
失败返回-1
互斥锁不能同步,多个任务依然保持异步执行,但是可以解决资源竞争
原子操作:最小的一次CPU操作,在执行原子操作时不会切换调度任务
3.死锁:
多线程加锁解锁导致多个任务均无法向下执行的状态称为死锁状态简称为死锁
死锁产生的4个必要条件:
1.互斥条件:同一把锁不能被多个线程任务同时锁定
2.不剥夺条件:不剥夺条件是指一个线程任务已经锁定了一个资源,不能被其他线程任务抢占,直到它使用完该资源
3.请求和保持条件:如果没有拿到锁资源一直申请获得锁资源
4.循环等待条件:如果没有得到锁资源会一直等待
如何避免产生死锁:
1.加锁顺序保持一致
2.打破互斥条件、不可剥夺条件(不建议使用)
3.使用pthread_mutex_trylock替代pthread_mutex_lock
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 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | #include "../head.h" pthread_mutex_t lock; int num = 0; void *thread1(void *arg) { while (1) { pthread_mutex_lock(&lock); num = 100; pthread_mutex_unlock(&lock); } return NULL; } void *thread2(void *arg) { while (1) { pthread_mutex_lock(&lock); num = 200; printf("num = %d\n", num); pthread_mutex_unlock(&lock); } return NULL; } int main(void) { pthread_t tid1; pthread_t tid2; pthread_mutex_init(&lock, NULL); pthread_create(&tid1, NULL, thread1, NULL); pthread_create(&tid2, NULL, thread2, NULL); pthread_join(tid1, NULL); pthread_join(tid2, NULL); pthread_mutex_destroy(&lock); return 0; } |
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 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | #include "../head.h" int num = 100; int value1 = 0; int value2 = 0; pthread_mutex_t lock; void *thread1(void *arg) { while (1) { pthread_mutex_lock(&lock); value1 = num; value2 = num; pthread_mutex_unlock(&lock); num++; } return NULL; } void *thread2(void *arg) { while (1) { pthread_mutex_lock(&lock); if (value1 != value2) { printf("value1 = %d, value2 = %d\n", value1, value2); } pthread_mutex_unlock(&lock); } return NULL; } int main(void) { pthread_t tid1; pthread_t tid2; pthread_mutex_init(&lock, NULL); pthread_create(&tid1, NULL, thread1, NULL); pthread_create(&tid2, NULL, thread2, NULL); pthread_join(tid1, NULL); pthread_join(tid2, NULL); pthread_mutex_destroy(&lock); return 0; } |
4.信号量:
实现多线程间同步
信号量是一种资源(可以初始化、销毁、申请、释放)
申请:资源数 > 0 申请操作让资源数-1
资源数 == 0 申请操作会阻塞,直到资源数不为0,申请得到资源后继续向下执行
释放:资源数+1
释放操作让资源数+1
sem_init
int sem_init(sem_t *sem, int pshared, unsigned int value);
功能:
对信号量的初始化
参数:
sem:信号量空间首地址
pshared:
0 线程间共享
非0 进程间共享
value:信号量的初始值
返回值:
成功返回0
失败返回-1
int sem_destroy(sem_t *sem);
功能:
信号量的销毁
int sem_wait(sem_t *sem);
功能:
申请信号量(资源数-1)
资源数为0阻塞等待直到有资源申请后继续向下执行
int sem_post(sem_t *sem);
功能:
释放信号量(资源数+1)
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 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | #include "../head.h" char tmpbuff[4096] = {0}; sem_t sem_r; sem_t sem_w; void *thread1(void *arg) { while (1) { sem_wait(&sem_w); gets(tmpbuff); sem_post(&sem_r); } return NULL; } void *thread2(void *arg) { while (1) { sem_wait(&sem_r); printf("tmpbuff = %s\n", tmpbuff); sem_post(&sem_w); } return NULL; } int main(void) { pthread_t tid1; pthread_t tid2; sem_init(&sem_w, 0, 1); sem_init(&sem_r, 0, 0); pthread_create(&tid1, NULL, thread1, NULL); pthread_create(&tid2, NULL, thread2, NULL); pthread_join(tid1, NULL); pthread_join(tid2, NULL); sem_destroy(&sem_w); sem_destroy(&sem_r); return 0; } |