zoukankan      html  css  js  c++  java
  • 三十九、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
    ", 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
    ", 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
    ", 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

    编译运行结果:

      

  • 相关阅读:
    java数组基础
    java异常处理机制
    java面向对象基础(四):抽象类和接口
    java面向对象基础(二)
    java类路径classpath和包
    java面向对象基础(一)
    Tomcat(二):tomcat配置文件server.xml详解和部署简介
    java集合框架(Collections Framework)
    java基础数据类型包装类
    String、StringBuilder和StringBuffer类
  • 原文地址:https://www.cnblogs.com/kele-dad/p/10222255.html
Copyright © 2011-2022 走看看