/*
#include <pthread.h>
int pthread_cancel(pthread_t thread);
- 功能:取消线程(让线程终止)
取消某个线程,可以终止某个线程的运行,
但是并不是立马终止,而是当子线程执行到一个取消点,线程才会终止。
取消点:系统规定好的一些系统调用
*/#include<stdio.h>#include<pthread.h>#include<string.h>#include<unistd.h>void*callback(void* arg){printf("chid thread id : %ld\n",pthread_self());for(int i =0; i <5; i++){printf("child : %d\n", i);}returnNULL;}intmain(){// 创建一个子线程
pthread_t tid;int ret =pthread_create(&tid,NULL, callback,NULL);if(ret !=0){char* errstr =strerror(ret);printf("error1 : %s\n", errstr);}// 取消线程pthread_cancel(tid);for(int i =0; i <5; i++){printf("%d\n", i);}// 输出主线程和子线程的idprintf("tid : %ld, main thread id : %ld\n", tid,pthread_self());pthread_exit(NULL);return0;}
4.6 线程属性相关函数
- 线程属性类型 pthread_attr_t
- int pthread_attr_init(pthread_attr_t *attr);
- int pthread_attr_destroy(pthread_attr_t *attr);
- int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate);
- int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
/*
int pthread_attr_init(pthread_attr_t *attr);
- 初始化线程属性变量
int pthread_attr_destroy(pthread_attr_t *attr);
- 释放线程属性的资源
int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate);
- 获取线程分离的状态属性
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
- 设置线程分离的状态属性
*/#include<stdio.h>#include<pthread.h>#include<string.h>#include<unistd.h>void*callback(void* arg){printf("chid thread id : %ld\n",pthread_self());returnNULL;}intmain(){// 创建一个线程属性变量
pthread_attr_t attr;// 初始化属性变量pthread_attr_init(&attr);// 设置属性pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);// 创建一个子线程
pthread_t tid;int ret =pthread_create(&tid,&attr, callback,NULL);if(ret !=0){char* errstr =strerror(ret);printf("error1 : %s\n", errstr);}// 获取线程的栈的大小
size_t size;pthread_attr_getstacksize(&attr,&size);printf("thread stack size : %ld\n", size);// 输出主线程和子线程的idprintf("tid : %ld, main thread id : %ld\n", tid,pthread_self());// 释放线程属性资源pthread_attr_destroy(&attr);pthread_exit(NULL);return0;}
- 读写锁的类型 pthread_rwlock_t
- int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr);
- int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
- int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
- int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
- int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
- int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
- int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
/*
案例:8个线程操作同一个全局变量。
3个线程不定时写这个全局变量,5个线程不定时的读这个全局变量
*/#include<stdio.h>#include<pthread.h>#include<unistd.h>// 创建一个共享数据int num =1;// pthread_mutex_t mutex;
pthread_rwlock_t rwlock;void*writeNum(void* arg){while(1){pthread_rwlock_wrlock(&rwlock);
num++;printf("++write, tid : %ld, num : %d\n",pthread_self(), num);pthread_rwlock_unlock(&rwlock);usleep(100);}returnNULL;}void*readNum(void* arg){while(1){pthread_rwlock_rdlock(&rwlock);printf("===read, tid : %ld, num : %d\n",pthread_self(), num);pthread_rwlock_unlock(&rwlock);usleep(100);}returnNULL;}intmain(){pthread_rwlock_init(&rwlock,NULL);// 创建3个写线程,5个读线程
pthread_t wtids[3], rtids[5];for(int i =0; i <3; i++){pthread_create(&wtids[i],NULL, writeNum,NULL);}for(int i =0; i <5; i++){pthread_create(&rtids[i],NULL, readNum,NULL);}// 设置线程分离for(int i =0; i <3; i++){pthread_detach(wtids[i]);}for(int i =0; i <5; i++){pthread_detach(rtids[i]);}pthread_exit(NULL);pthread_rwlock_destroy(&rwlock);return0;}
6 生产者消费者模型
/*
生产者消费者模型(粗略的版本)
*/#include<stdio.h>#include<pthread.h>#include<stdlib.h>#include<unistd.h>// 创建一个互斥量
pthread_mutex_t mutex;structNode{int num;structNode*next;};// 头结点structNode* head =NULL;void*producer(void* arg){// 不断的创建新的节点,添加到链表中while(1){pthread_mutex_lock(&mutex);structNode* newNode =(structNode*)malloc(sizeof(structNode));
newNode->next = head;
head = newNode;
newNode->num =rand()%1000;printf("add node, num : %d, tid : %ld\n", newNode->num,pthread_self());pthread_mutex_unlock(&mutex);usleep(100);}returnNULL;}void*customer(void* arg){while(1){pthread_mutex_lock(&mutex);// 保存头结点的指针structNode* tmp = head;// 判断是否有数据if(head !=NULL){// 有数据
head = head->next;printf("del node, num : %d, tid : %ld\n", tmp->num,pthread_self());free(tmp);pthread_mutex_unlock(&mutex);usleep(100);}else{// 没有数据pthread_mutex_unlock(&mutex);}}returnNULL;}intmain(){pthread_mutex_init(&mutex,NULL);// 创建5个生产者线程,和5个消费者线程
pthread_t ptids[5], ctids[5];for(int i =0; i <5; i++){pthread_create(&ptids[i],NULL, producer,NULL);pthread_create(&ctids[i],NULL, customer,NULL);}for(int i =0; i <5; i++){pthread_detach(ptids[i]);pthread_detach(ctids[i]);}while(1){sleep(10);}pthread_mutex_destroy(&mutex);pthread_exit(NULL);return0;}
7 条件变量
- 条件变量的类型 pthread_cond_t
- int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);
- int pthread_cond_destroy(pthread_cond_t *cond);
- int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
- int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict abstime);
- int pthread_cond_signal(pthread_cond_t *cond);
- int pthread_cond_broadcast(pthread_cond_t *cond);
/*
条件变量的类型 pthread_cond_t
int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);
- 初始化
int pthread_cond_destroy(pthread_cond_t *cond);
- 释放
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
- 等待,调用了该函数,线程会阻塞。
int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict abstime);
- 等待多长时间,调用了这个函数,线程会阻塞,直到指定的时间结束。
int pthread_cond_signal(pthread_cond_t *cond);
- 唤醒一个或者多个等待的线程
int pthread_cond_broadcast(pthread_cond_t *cond);
- 唤醒所有的等待的线程
*/#include<stdio.h>#include<pthread.h>#include<stdlib.h>#include<unistd.h>// 创建一个互斥量
pthread_mutex_t mutex;// 创建条件变量
pthread_cond_t cond;structNode{int num;structNode*next;};// 头结点structNode* head =NULL;void*producer(void* arg){// 不断的创建新的节点,添加到链表中while(1){pthread_mutex_lock(&mutex);structNode* newNode =(structNode*)malloc(sizeof(structNode));
newNode->next = head;
head = newNode;
newNode->num =rand()%1000;printf("add node, num : %d, tid : %ld\n", newNode->num,pthread_self());// 只要生产了一个,就通知消费者消费pthread_cond_signal(&cond);pthread_mutex_unlock(&mutex);usleep(100);}returnNULL;}void*customer(void* arg){while(1){pthread_mutex_lock(&mutex);// 保存头结点的指针structNode* tmp = head;// 判断是否有数据if(head !=NULL){// 有数据
head = head->next;printf("del node, num : %d, tid : %ld\n", tmp->num,pthread_self());free(tmp);pthread_mutex_unlock(&mutex);usleep(100);}else{// 没有数据,需要等待// 当这个函数调用阻塞的时候,会对互斥锁进行解锁,当不阻塞的,继续向下执行,会重新加锁。pthread_cond_wait(&cond,&mutex);pthread_mutex_unlock(&mutex);}}returnNULL;}intmain(){pthread_mutex_init(&mutex,NULL);pthread_cond_init(&cond,NULL);// 创建5个生产者线程,和5个消费者线程
pthread_t ptids[5], ctids[5];for(int i =0; i <5; i++){pthread_create(&ptids[i],NULL, producer,NULL);pthread_create(&ctids[i],NULL, customer,NULL);}for(int i =0; i <5; i++){pthread_detach(ptids[i]);pthread_detach(ctids[i]);}while(1){sleep(10);}pthread_mutex_destroy(&mutex);pthread_cond_destroy(&cond);pthread_exit(NULL);return0;}
8 信号量
- 信号量的类型 sem_t
- int sem_init(sem_t *sem, int pshared, unsigned int value);
- int sem_destroy(sem_t *sem);
- int sem_wait(sem_t *sem);
- int sem_trywait(sem_t *sem);
- int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);
- int sem_post(sem_t *sem);
- int sem_getvalue(sem_t *sem, int *sval);
/*
信号量的类型 sem_t
int sem_init(sem_t *sem, int pshared, unsigned int value);
- 初始化信号量
- 参数:
- sem : 信号量变量的地址
- pshared : 0 用在线程间 ,非0 用在进程间
- value : 信号量中的值
int sem_destroy(sem_t *sem);
- 释放资源
int sem_wait(sem_t *sem);
- 对信号量加锁,调用一次对信号量的值-1,如果值为0,就阻塞
int sem_trywait(sem_t *sem);
int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);
- 设置阻塞多长时间
int sem_post(sem_t *sem);
- 对信号量解锁,调用一次对信号量的值+1
int sem_getvalue(sem_t *sem, int *sval);
- 获取 sem 的值,并放到 sval 指向的内存
sem_t psem;
sem_t csem;
init(psem, 0, 8);
init(csem, 0, 0);
producer() {
sem_wait(&psem);
sem_post(&csem)
}
customer() {
sem_wait(&csem);
sem_post(&psem)
}
*/#include<stdio.h>#include<pthread.h>#include<stdlib.h>#include<unistd.h>#include<semaphore.h>// 创建一个互斥量
pthread_mutex_t mutex;// 创建两个信号量
sem_t psem;
sem_t csem;structNode{int num;structNode*next;};// 头结点structNode* head =NULL;void*producer(void* arg){// 不断的创建新的节点,添加到链表中while(1){sem_wait(&psem);pthread_mutex_lock(&mutex);structNode* newNode =(structNode*)malloc(sizeof(structNode));
newNode->next = head;
head = newNode;
newNode->num =rand()%1000;printf("add node, num : %d, tid : %ld\n", newNode->num,pthread_self());pthread_mutex_unlock(&mutex);sem_post(&csem);}returnNULL;}void*customer(void* arg){while(1){sem_wait(&csem);pthread_mutex_lock(&mutex);// 保存头结点的指针structNode* tmp = head;
head = head->next;printf("del node, num : %d, tid : %ld\n", tmp->num,pthread_self());free(tmp);pthread_mutex_unlock(&mutex);sem_post(&psem);}returnNULL;}intmain(){pthread_mutex_init(&mutex,NULL);sem_init(&psem,0,8);sem_init(&csem,0,0);// 创建5个生产者线程,和5个消费者线程
pthread_t ptids[5], ctids[5];for(int i =0; i <5; i++){pthread_create(&ptids[i],NULL, producer,NULL);pthread_create(&ctids[i],NULL, customer,NULL);}for(int i =0; i <5; i++){pthread_detach(ptids[i]);pthread_detach(ctids[i]);}while(1){sleep(10);}pthread_mutex_destroy(&mutex);pthread_exit(NULL);return0;}