三十九Linux 线程——线程的同步和互斥
Posted 游戏进行中
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了三十九Linux 线程——线程的同步和互斥相关的知识,希望对你有一定的参考价值。
39.1 概念
- 线程同步
- 是一个宏观概念,在微观上包含线程的相互排斥和线程先后执行的约束问题
- 解决同步方式
- 条件变量
- 线程信号量
- 线程互斥
- 线程执行的相互排斥
- 解决互斥的方式
- 互斥锁
- 读写锁
- 线程信号量
39.2 案例
atm_account.c
1 #include "atm_account.h" 2 3 /** 创建账户 */ 4 atm_Account *atm_account_Create(int code, double balance) 5 { 6 atm_Account *account = (atm_Account *)malloc(sizeof(atm_Account)); 7 if(NULL == account) { 8 return NULL; 9 } 10 11 account->code = code; 12 account->balance = balance; 13 14 return account; 15 } 16 17 /** 销毁账户 */ 18 void atm_account_Destroy(atm_Account *account) 19 { 20 if(NULL == account){ 21 return ; 22 } 23 24 free(account); 25 } 26 27 /** 取款: 成功,则返回取款金额 */ 28 double atm_account_Withdraw(atm_Account *account, double amt) 29 { 30 if(NULL == account) { 31 return 0.0; 32 } 33 34 if(amt < 0 || amt > account->balance) { 35 return 0.0; 36 } 37 38 double balance_tmp = account->balance; 39 sleep(1); 40 balance_tmp -= amt; 41 account->balance = balance_tmp; 42 43 return amt; 44 } 45 46 /** 存款: 返回存款的金额 */ 47 double atm_account_Desposit(atm_Account *account, double amt) 48 { 49 if(NULL == account){ 50 return 0.0; 51 } 52 if(amt < 0){ 53 return 0.0; 54 } 55 56 double balance_tmp = account->balance; 57 sleep(1); 58 balance_tmp += amt; 59 account->balance = balance_tmp; 60 61 return amt; 62 } 63 64 /** 查看账户余额 */ 65 double atm_account_BalanceGet(atm_Account *account) 66 { 67 if(NULL == account){ 68 return 0.0; 69 } 70 71 double balance_tmp = account->balance; 72 return balance_tmp; 73 }
atm_account.h
1 #ifndef __ATM_ACCOUNT_H__ 2 #define __ATM_ACCOUNT_H__ 3 4 #include <math.h> 5 #include <malloc.h> 6 #include <stdlib.h> 7 #include <stdio.h> 8 #include <string.h> 9 #include <unistd.h> 10 11 /** 账户信息 */ 12 typedef struct { 13 int code; ///< 银行账户的编码 14 double balance; ///< 账户余额 15 }atm_Account; 16 17 /** 创建账户 */ 18 extern atm_Account *atm_account_Create(int code, double balance); 19 /** 销毁账户 */ 20 extern void atm_account_Destroy(atm_Account *account); 21 /** 取款 */ 22 extern double atm_account_Withdraw(atm_Account *account, double amt); 23 /** 存款 */ 24 extern double atm_account_Desposit(atm_Account *account, double amt); 25 /** 查看账户余额 */ 26 extern double atm_account_BalanceGet(atm_Account *account); 27 28 #endif
atm_handler.c
1 #include "atm_handler.h" 2 3 /** 定义取款操作的线程运行函数 */ 4 void *atm_handler_Withdraw(void *arg) 5 { 6 atm_handler_t *handler_tmp = (atm_handler_t *)arg; 7 double amt = atm_account_Withdraw(handler_tmp->account, handler_tmp->amt); 8 9 printf("%10s(0x%lu) withdraw %f from account %d\\n", handler_tmp->name, pthread_self(), amt, handler_tmp->account->code); 10 11 return (void *)0; 12 } 13 14 /** 定义存款操作的线程运行函数 */ 15 void *atm_handler_Desposit(void *arg) 16 { 17 atm_handler_t *handler_tmp = (atm_handler_t *)arg; 18 double amt = atm_account_Desposit(handler_tmp->account, handler_tmp->amt); 19 20 printf("%10s(0x%lu) deposit %f from account %d\\n", handler_tmp->name, pthread_self(), amt, handler_tmp->account->code); 21 22 return (void *)0; 23 } 24 25 /** 定义检查银行账户的线程运行函数 */ 26 void *atm_handler_AccountCheck(void *arg) 27 { 28 return (void *)0; 29 } 30 31 /** 账户操作主函数 */ 32 atm_error_t atm_handler_main(void) 33 { 34 int err; 35 pthread_t boy, girl; 36 atm_Account *account = atm_account_Create(1000001, 10000); 37 if(NULL == account){ 38 return ATM_ERROR_ACCOUNT_CREATE; 39 } 40 41 atm_handler_t usr1, usr2; 42 strcpy(usr1.name, "boy"); 43 usr1.account = account; 44 usr1.amt = 10000; 45 46 strcpy(usr2.name, "girl"); 47 usr2.account = account; 48 usr2.amt = 10000; 49 50 /** 启动两个线程(boy 和 girl 线程)同时去操作同一个银行账户 */ 51 if((err = pthread_create(&boy, NULL, atm_handler_Withdraw, (void *)&usr1)) != 0) { 52 perror("pthread create error"); 53 } 54 55 if((err = pthread_create(&girl, NULL, atm_handler_Withdraw, (void *)&usr2)) != 0) { 56 perror("pthread create error"); 57 } 58 59 /** 主线程阻塞 */ 60 pthread_join(boy, NULL); 61 pthread_join(girl, NULL); 62 63 printf("account balance: %f\\n", atm_account_BalanceGet(account)); 64 atm_account_Destroy(account); 65 66 return ATM_ERROR_NONE; 67 }
atm_handler.h
1 #ifndef __ATM_HANDLER_H__ 2 #define __ATM_HANDLER_H__ 3 4 #include "atm_account.h" 5 #include <pthread.h> 6 #include <stdio.h> 7 #include <stdlib.h> 8 #include <string.h> 9 10 typedef enum { 11 ATM_ERROR_NONE, 12 ATM_ERROR_ACCOUNT_CREATE 13 }atm_error_t; 14 15 /** 账户操作结构体 */ 16 typedef struct { 17 char name[20]; ///< 操作人的姓名 18 atm_Account *account; ///< 操作的账户 19 double amt; ///< 操作的金额 20 }atm_handler_t; 21 22 extern atm_error_t atm_handler_main(void); 23 24 #endif
atm_test.c
1 #include "atm_handler.h" 2 3 int main(void) 4 { 5 atm_handler_main(); 6 return 0; 7 }
Makefile
#PROJECT_ROOT = $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) PROJECT_ROOT = $(shell pwd) SRC_DIR = $(PROJECT_ROOT)/src INCLUDE_DIR = $(PROJECT_ROOT)/include OBJ_DIR = $(PROJECT_ROOT)/obj BIN_DIR = $(PROJECT_ROOT)/bin # 找出 src 目录下的所有 .c 文件 C_SRCS = $(wildcard $(SRC_DIR)/*.c) # 将所有的 src 下的 .c 文件替换为 .o 文件 C_OBJS = $(patsubst %c, %o, $(C_SRCS)) TARGET = test SHARE_LIB = libatm.a C_SRC_MAIN = atm_test.c CC = gcc CCFLAGS += fPIC LDFLAGS += -shared -fPIC ASFLAGS += ARFLAGS = -crs LIBS_FLAGS = -L$(BIN_DIR) RM = rm -rf CFLAGS += -Wall -g -I$(INCLUDE_DIR) INCDIR += -I$(INCLUDE_DIR) .PHONY: all clean test all: $(TARGET) cp $(SHARE_LIB) $(BIN_DIR) cp $(SRC_DIR)/*.o $(OBJ_DIR)/ $(RM) $(SHARE_LIB) $(SRC_DIR)/*.o $(TARGET): $(SHARE_LIB) $(CC) $(C_SRC_MAIN) -o $(TARGET) $(CFLAGS) $(INCDIR) $(LIBS_FLAGS) -latm -lpthread $(SHARE_LIB): $(C_OBJS) $(AR) $(ARFLAGS) $(SHARE_LIB) $(C_OBJS) cp $(SHARE_LIB) $(BIN_DIR) $(C_OBJS) : %.o:%.c $(CC) -c $(CFLAGS) $(INCDIR) -o $@ $< -lpthread clean: $(RM) mshell $(RM) $(SHARE_LIB) $(RM) $(OBJ_DIR)/$(OBJS)/*.o $(RM) $(SRC_DIR)/*.o
编译运行结果:
以上是关于三十九Linux 线程——线程的同步和互斥的主要内容,如果未能解决你的问题,请参考以下文章
Qt系列文章之三十一 (基于QThread互斥量的线程同步线程)
Qt系列文章之三十二 (基于QThread的QReadWriteLock和QWaitCondition 的线程同步)
Qt系列文章之三十二 (基于QThread的QReadWriteLock和QWaitCondition 的线程同步)