//信号量的定义
sem_t sem;
int sem_t_init(sem_t *sem,int pshared,unsigned value);
int sem_t_destroy(sem_t *sem);
返回:成功返回0 出错返回错误编号
int sem_post(sem_t *sem); //功能:增加信号量的值
int sem_wait(sem_t *sem); //功能:减少信号量的值
int sem_trywait(sem_t *sem);//sem_wait()非阻塞版本
返回:成功返回0 出错返回错误编号
/*创建三个子线程,使用信号量去控制三个子线程的运行顺序。
*/
#include
#include
#include
#include
//定义两个线程信号量
sem_t sem1,sem2;
void* a_fn(void *arg){sem_wait(sem1);//此时sem1为0,再减一 线程堵塞printf("thread a running\n");return(void*)0;
}
void* b_fn(void *arg){sem_wait(sem2);//此时sem2为0,再减一 线程堵塞printf("thread b running\n");//释放线程a,让阻塞的线程a继续操作sem_post(sem1)return(void*)0;
}
void* c_fn(void *arg){printf("thread c running\n");//释放线程b(此时sem2为0,加1)//让阻塞的线程b继续运行sem_post(sem2);return(void*)0;
}
int main(void){int err;pthread_t a,b,c;//线程信号量的初始化,初始值为0sem_t_init(&sem1,0,0);sem_t_init(&sem2,0,0);//创建线程if ((err = pthread_create(&a, null, a_fn, (void*)0)) != 0) {perror("pthread_create error");}if ((err = pthread_create(&b, null, b_fn, (void*)0)) != 0) {perror("pthread_create error");}if ((err = pthread_create(&c, null, c_fn, (void*)0)) != 0) {perror("pthread_create error");}//主线程要等三个子线程执行完毕pthread_join(a,null);pthread_join(b,null);pthread_join(c,null);//线程信号的销毁sem_t_destroy(&sem1);sem_t_destroy(&sem2);return 0;
}
头文件 account.h
#ifndef __ACCOUNT_H__
#define __ACCOUNT_H__
#include
#include
//银行账户结构体
typedef struct{int code;//卡号double balance;//余额sem_t sem;//线程信号量}Account;
//创建账户
extern Account* creat_account(int code,double balance);
//销毁账户
extern void destory_account(Account *a);
//取款
extern double withdraw(Account *a,double amt);
//存款
extern double deposit(Account *a,double amt);
//查看账户余额
extern double get_balance(Account *a);
#endif
功能文件account.c
#include "account.h"
#include
#include
#include
#include
//创建账户
Account* creat_account(int code,double balance){//创建账户在堆当中Account *a = (Account*)malloc(sizeof(Account));assert(a != NULL);//用来判断a指针所需要开辟的空间,开辟成功了吗,成功就继续,否则就程序终止运行。a->code = code;a->balance = balance;//线程信号量的初始化,初始值为1sem_t_init(&a->sem,0,1);return a;
}
//销毁账户
void destory_account(Account *a){assert(a != NULL);//销毁线程信号量sem_t_destroy(&a->sem);free(a);//释放空间
}
//取款
double withdraw(Account *a,double amt){assert(a != NULL);//判断指针a是否为空//使信号量减一 锁定sem_wait(&a->sem);if(amt < 0 || amt > a->balance){//使信号量加一 解锁sem_post(&a->sem);return 0.0;}double balance = a->balance;sleep(1);balance -= amt;a->balance = balance;//使信号量加一 解锁sem_post(&a->sem);return amt;
}
//存款
double deposit(Account *a,double amt){assert(a != NULL);//使信号量减一 锁定sem_wait(&a->sem);if(amt < 0){//使信号量加一 解锁sem_post(&a->sem);return 0.0;}double balance = a->balance;sleep(1);balance += amt;a->balance = balance;//使信号量加一 解锁sem_post(&a->sem);return amt;
}
//查看账户余额
double get_balance(Account *a){assert(a != NULL);//使信号量减一 锁定sem_wait(&a->sem);double balance = a->balance;//使信号量加一 解锁sem_post(&a->sem);return balanec;
}
执行文件 account_test.c
#include "account.h"
#include
#include
#include
#include //操作者的结构体
typedef struct{char name[20];//操作者姓名Account *account;//账户double amt;//金额
}OperArg
//定义取款操作的线程运行函数
void* withdraw_fn(void *arg){OperArg *oa = (OperArg*)arg;//deposit存款函数double amt = deposit(oa->account,oa->amt);printf("%8s(0x%lx) deposit %f from account %d/n",oa->name,pthread_self(),amt,oa->account->code);return (void*)0;
}
//定义存款操作的线程运行函数
void* deposit_fn(void *arg){OperArg *oa = (OperArg*)arg;//withdraw取款函数double amt = withdraw(oa->account,oa->amt);printf("%8s(0x%lx) withdraw %f from account %d/n",oa->name,pthread_self(),amt,oa->account->code);return (void*)0;
}
//定义查看银行账户的线程运行函数
void* check_fn(void *arg){}
int main(void){int err;pthread_t boy,girl;Account *a = create_account(10001,10000)//卡号,余额OperArg o1 , o2;//两个操作者strcpy(o1.name,"boy");//strcpy()把第二个参数值,放到第一个参数中o1.account = a;o1.amt = 10000;strcpy(o2.name,"girl");o2.account = a;o2.amt = 10000;//启动两个子线程(boy和girl)同时去操作同一个银行账户if((err = pthread_create(&boy,null,withdraw_fn,(void*)&o1)!=0){printf("pthread create error");}if((err = pthread_create(&girl,null,withdraw_fn,(void*)&o2)!=0){printf("pthread create error");}pthread_join(boy,null);pthread_join(girl,null);//查看账户余额printf("account balance %f/n",get_balance(a));//销毁账户destroy_account(a);return 0;
}
程序运行结果:
思路:
#include
#include
#include
#include
/*一个线程赋值计算结果,一个线程负责获取结果当计算结果的线程没有执行完毕,获取结果的线程要等待(阻塞)
*/
typedef struct{int res;//存放运算结果sem_t sem//线程信号量
}Result;//计算并将结果放置Result中的线程运行函数
void* set_fn(void *arg){int sum;for(int i =1;i<=100;i++){sum +=i;}//将结果存放到ResultResult *r = (Result*)arg;r->res = sum;//对线程信号量 加一 sem_post(&r->sem);return(void*) 0;
}//获得结果的线程运行函数
void* get_fn(void *arg){Result *r = (Result*)arg;//对线程信号量 减一 sem_wait(&r->sem);//去获取计算的结果int res = r->res;printf("ox%lx get sum is %d\n",pthread_self(),res);return(void*)0;
}int main(void){int err;//定义线程标识符cal getpthread_t cal, get;//线程信号量初始化sem_init(&r.sem,0.0);//启动获取结果的线程if ((err = pthread_create(&get, NULL, get_fn, (void*)&r)) != 0) {perror("pthread_create error");}//启动计算结果的线程if ((err = pthread_create(&cal, NULL, set_fn, (void*)&r)) != 0) {perror("pthread_create error");}//主线程要等两个子线程执行完毕pthread_join(get,null);pthread_join(cal,null);//线程信号量的销毁sem_destroy(&r.sem);return 0;
}
程序运行结果: