#include
#include
int num = 0;
void* start_run(void* arg){
for(int i=0;i<1000000;i++){
num++;
}
}
int main(){
pthread_t pid[10] = {};
for(inti =0;i<10;i++){
pthread_create(&pid[i],NULL,start_run,NULL);
}
for(int i=0;i<10;i++){
pthread_join(pid[i],NULL);
}
printf("%d\n",num);
}
//运行结果600W+,理论是1000W,为啥?
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int pthread_mutex_init(pthread_mutex_t * __mutex,__const pthread_mutexattr_t *__mutexattr);
int pthread_mutex_destroy(pthread_mutex_t *__mutex);
int pthread_mutex_trylock(pthread_mutex_t *__mutex);
int pthread_mutex_lock(pthread_mutex_t *__mutex);
int pthread_mutex_timedlock(pthread_mutex_t *__restrict __mutex,const struct timespec *__restrict_abstime);
struct timespec{
__time_t tv_sec;
long int tv_nsec;
}
int pthread_mutex_unlock (pthread_mutex_t *__mutex);
//用法1
#include
#include
#include
int num = 0;
//定义一个互斥量并初始化
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void* start_run(void* arg){
for(int i=0;i<1000000;i++){
pthread_mutex_lock(&mutex);
num++;
pthread_mutex_unlock(&mutex);
}
}
int main(){
pthread_t pid[10] = {};
for(inti =0;i<10;i++){
pthread_create(&pid[i],NULL,start_run,NULL);
}
for(int i=0;i<10;i++){
pthread_join(pid[i],NULL);
}
printf("%d\n",num);
pthread_mutex_destroy(&mutex);
}
//用法2
void* start_run(void* arg){
for(int i=0;i<1000000;i++){
pthread_mutex_lock((pthread_mutex_t*)arg);
num++;
pthread_mutex_unlock((pthread_mutex_t*)arg);
}
}
int main(){
pthread_mutex_t* mutex = malloc(sizeof(pthread_mutex_t));
pthread_mutex_init(mutex);
pthread_t pid[10] = {};
for(inti =0;i<10;i++){
pthread_create(&pid[i],NULL,start_run,mutex);
}
for(int i=0;i<10;i++){
pthread_join(pid[i],NULL);
}
printf("%d\n",num);
pthread_mutex_destroy(&mutex);
}
#include
#include
#include
pthread_mutex_t key = PYHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mouse = PYHREAD_MUTEX_INITIALIZER;
void* ming(void* arg){
pthread_mutex_lock(&key);
usleep(100);
pthread_mutex_lock(&mouse);
printf("键盘和鼠标都拿到了,可以开心打游戏了\n");
sleep(5);
pthread_mutex_unlock(&mouse);
pthread_mutex_unlock(&key);
}
void* huang(void* arg){
pthread_mutex_lock(&mouse);
usleep(100);
pthread_mutex_lock(&key);
printf("键盘和鼠标都拿到了,可以开心ppt了\n");
sleep(5);
pthread_mutex_unlock(&mouse);
pthread_mutex_unlock(&key);
}
int main(){
pthread_t pid1;
pthread_create(pid1,NULL,ming,NULL);
pthread_T pid2;
pthread_create(pud2,NULL,huang,NULL);
pthread_join(pid1,NULL);
pthread_join(pid2,NULL);
}
//两个线程都无法返回,产生死锁
多个线程进行等待对方的资源,在得到所有资源继续运行前,都不会释放自己的资源,这样造成的循环等待现象,称为死锁
构成死锁的四大必要条件:
防止死锁的方法:
构成死锁的四个条件只要破坏其中一个就构不成死锁,死锁一旦形成,就无法消除,因此最好的方法就是避免产生死锁
避免死锁产生的算法(银行家算法)
如何检测死锁(判断一个进程的线程是否进入死锁)
线程的信号量,进程的信号量的机制是一样的,但使用方法不同,用于控制,管理线程间的共享资源
sem_init - initialize an unnamed semaphore
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_destroy(sem_t *sem);
int sem_getvalue(sem_t *sem, int *sval);
#include
#include
#include
#include
int num;
sem_t sem;
void* start_run(void* arg){
for(int i=0;i<1000000;i++){
sem_wait(&sem);
num++;
sem_post(&sem);
}
}
int main(){
sem_init(&sem,0,1);
pthread_t pid[10] = {};
for(inti =0;i<10;i++){
pthread_create(&pid[i],NULL,start_run,NULL);
}
for(int i=0;i<10;i++){
pthread_join(pid[i],NULL);
}
printf("%d\n",num);
sem_destroy(&sem);
}
#include
#include
#include
sem_t sem;
void* start_run(void* arg){
sem_wait(&sem);
int value = 0;
sem_getvalue(&sem,&value);
printf("%u:我骑走一头小毛驴,还有%d头小毛驴\n",pthread_self(),value);
sem_post(&sem);
sleep(rand()%10);
sem_getvalue(&sem,&value);
printf("%u:我骑走一头小毛驴,还有%d头小毛驴\n",pthread_self(),value);
}
int main(){
//初始化3头小毛驴
sem_init(&sem,0,3);
pthread_t pid[5];
for(int i=0;i<5;i++){
pthread_create(&pid[i],NULL,start_run,NULL);
}
for(int i=0;i<5;i++){
pthread_join(pid[i],NULL);
}
}
生产者与消费者模型
生产者:产生数据的线程 消费者:使用数据的线程
┌───────┐ ┌───────┐
|pthread│ ┌──────────────────────────┐ |pthread│
├───────┤ => |temporary buffer for datas| => ├───────┤
|pthread| └──────────────────────────┘ |pthread|
└───────┘ └───────┘
#include
#include
#include
#include
#include
#define HOUSE_MAX 20
//栈结构
char house[HOUSE_MAX] = {};
//栈顶下标
int top = 0;
//互斥量(确保只有一个线程访问栈顶)
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
//满仓条件变量(爆仓时,生产线程睡)
pthread_cond_t full = PTHREAD_COND_INITIALIZER;
//空仓条件变量(空仓时,消费线程睡)
pthread_cond_t null = PTHREAD_COND_INITIALIZER;
//显式仓库
void show_house(char* who, char* op, char ch){
printf("%s:",who);
for(int i=0; i<=top; i++){
printf("%c",house[i]);
}
printf("%s%c\n",op,ch);
}
//生产者线程
void* production(void* arg){
char* who = (char*)arg;
for(;;){
char ch = 'A'+rand()%26;
pthread_mutex_lock(&mutex);
//醒来后再次检查是否满仓
while(HOUSE_MAX <= top){
printf("%s:满仓\n",who);
pthread_cond_wait(&full,mutex);
}
//入仓数据
house[top++] = ch;
//模拟现时情况
usleep(rand()%100000);
//解锁
pthread_mutex_unlock(&mutex);
//已经确保仓库不空,通知消费
pthread_cond_signal(&null);
}
return NULL;
}
//消费者线程
void* consume(void* arg){
char* who = (char*)arg;
for(;;){
//加锁
pthread_mutex_lock(&mutex);
//检查仓库是否空
while(0 == top){
printf("%s:空仓\n",who);
pthread_cond_wait(&null,&mutex);
}
//消费数据
char ch = house[top--];
show_house(who,"->",ch);
usleep(rand()%100000);
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&full);
}
}
int main(){
srand(time(NULL));
pthread_t pid[6] = {};
pthread_create(&pid[0],NULL,production,"生产1");
pthread_create(&pid[1],NULL,production,"生产2");
pthread_create(&pid[2],NULL,production,"生产3");
pthread_create(&pid[3],NULL,consume,"消费1");
pthread_create(&pid[4],NULL,consume,"消费2");
pthread_create(&pid[5],NULL,consume,"消费3");
for(int i=0;i<6;i++){
pthread_join(pid[i]);
}
}
int pthread_cond_init (pthread_cond_t *cond,pthread_condattr_t *__restrict_cond_attr);
pthread_cond_destroy(pthread_cond_t *cond);
pthread_cond_singal(pthread_cond_t *cond);
pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
pthread_cond_timewait(pthread_cond_t *cond, pthread_mutex_t *mutex, struct timespace __abstimr)
#include
#include
#include
//定义并初始化条件变量
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void* start_run(void* arg){
printf("我将进入睡眠\n");
pthread_cond_wait(&cond,&mutex);
printf("我醒了\n");
}
int main(){
pthread_t pid;
pthread_create(&pid,NULL,start_run,NULL);
sleep(3);
//pthread_mutex_lock(&mutex); 如果唤醒前加锁,无法唤醒
pthread_cond_signal(&cond);
pthread_join(pid,NULL);
}
void *start_run(void* arg){
struct timrval now;
struct timespec t;
gettimeofday(&now,NUll);
t.tv_sec =
pthread_cond_timewait
}
哲学家就餐问题可以这样表述,假设有五位哲学家围坐在一张圆形餐桌旁,做以下两件事情之一:吃饭,或者思考。吃东西的时候,他们就停止思考,思考的时候也停止吃东西。餐桌中间有一大碗意大利面,每两个哲学家之间有一只餐叉。因为用一只餐叉很难吃到意大利面,所以假设哲学家必须用两只餐叉吃东西。他们只能使用自己左右手边的那两只餐叉。哲学家就餐问题有时也用米饭和筷子而不是意大利面和餐叉来描述,因为很明显,吃米饭必须用两根筷子。