39.1 概念

  • 线程同步

    • 是一个宏观概念,在微观上包含线程的相互排斥和线程先后执行的约束问题
    • 解决同步方式
      • 条件变量
      • 线程信号量
  • 线程互斥
    • 线程执行的相互排斥
    • 解决互斥的方式
      • 互斥锁
      • 读写锁
      • 线程信号量

39.2 案例

  

atm_account.c

 #include "atm_account.h"

 /** 创建账户 */
atm_Account *atm_account_Create(int code, double balance)
{
atm_Account *account = (atm_Account *)malloc(sizeof(atm_Account));
if(NULL == account) {
return NULL;
} account->code = code;
account->balance = balance; return account;
} /** 销毁账户 */
void atm_account_Destroy(atm_Account *account)
{
if(NULL == account){
return ;
} free(account);
} /** 取款: 成功,则返回取款金额 */
double atm_account_Withdraw(atm_Account *account, double amt)
{
if(NULL == account) {
return 0.0;
} if(amt < || amt > account->balance) {
return 0.0;
} double balance_tmp = account->balance;
sleep();
balance_tmp -= amt;
account->balance = balance_tmp; return amt;
} /** 存款: 返回存款的金额 */
double atm_account_Desposit(atm_Account *account, double amt)
{
if(NULL == account){
return 0.0;
}
if(amt < ){
return 0.0;
} double balance_tmp = account->balance;
sleep();
balance_tmp += amt;
account->balance = balance_tmp; return amt;
} /** 查看账户余额 */
double atm_account_BalanceGet(atm_Account *account)
{
if(NULL == account){
return 0.0;
} double balance_tmp = account->balance;
return balance_tmp;
}

atm_account.h

 #ifndef __ATM_ACCOUNT_H__
#define __ATM_ACCOUNT_H__ #include <math.h>
#include <malloc.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h> /** 账户信息 */
typedef struct {
int code; ///< 银行账户的编码
double balance; ///< 账户余额
}atm_Account; /** 创建账户 */
extern atm_Account *atm_account_Create(int code, double balance);
/** 销毁账户 */
extern void atm_account_Destroy(atm_Account *account);
/** 取款 */
extern double atm_account_Withdraw(atm_Account *account, double amt);
/** 存款 */
extern double atm_account_Desposit(atm_Account *account, double amt);
/** 查看账户余额 */
extern double atm_account_BalanceGet(atm_Account *account); #endif

atm_handler.c

 #include "atm_handler.h"

 /** 定义取款操作的线程运行函数 */
void *atm_handler_Withdraw(void *arg)
{
atm_handler_t *handler_tmp = (atm_handler_t *)arg;
double amt = atm_account_Withdraw(handler_tmp->account, handler_tmp->amt); printf("%10s(0x%lu) withdraw %f from account %d\n", handler_tmp->name, pthread_self(), amt, handler_tmp->account->code); return (void *);
} /** 定义存款操作的线程运行函数 */
void *atm_handler_Desposit(void *arg)
{
atm_handler_t *handler_tmp = (atm_handler_t *)arg;
double amt = atm_account_Desposit(handler_tmp->account, handler_tmp->amt); printf("%10s(0x%lu) deposit %f from account %d\n", handler_tmp->name, pthread_self(), amt, handler_tmp->account->code); return (void *);
} /** 定义检查银行账户的线程运行函数 */
void *atm_handler_AccountCheck(void *arg)
{
return (void *);
} /** 账户操作主函数 */
atm_error_t atm_handler_main(void)
{
int err;
pthread_t boy, girl;
atm_Account *account = atm_account_Create(, );
if(NULL == account){
return ATM_ERROR_ACCOUNT_CREATE;
} atm_handler_t usr1, usr2;
strcpy(usr1.name, "boy");
usr1.account = account;
usr1.amt = ; strcpy(usr2.name, "girl");
usr2.account = account;
usr2.amt = ; /** 启动两个线程(boy 和 girl 线程)同时去操作同一个银行账户 */
if((err = pthread_create(&boy, NULL, atm_handler_Withdraw, (void *)&usr1)) != ) {
perror("pthread create error");
} if((err = pthread_create(&girl, NULL, atm_handler_Withdraw, (void *)&usr2)) != ) {
perror("pthread create error");
} /** 主线程阻塞 */
pthread_join(boy, NULL);
pthread_join(girl, NULL); printf("account balance: %f\n", atm_account_BalanceGet(account));
atm_account_Destroy(account); return ATM_ERROR_NONE;
}

atm_handler.h

 #ifndef __ATM_HANDLER_H__
#define __ATM_HANDLER_H__ #include "atm_account.h"
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h> typedef enum {
ATM_ERROR_NONE,
ATM_ERROR_ACCOUNT_CREATE
}atm_error_t; /** 账户操作结构体 */
typedef struct {
char name[]; ///< 操作人的姓名
atm_Account *account; ///< 操作的账户
double amt; ///< 操作的金额
}atm_handler_t; extern atm_error_t atm_handler_main(void); #endif

atm_test.c

 #include "atm_handler.h"

 int main(void)
{
atm_handler_main();
return ;
}

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 线程——线程的同步和互斥的更多相关文章

  1. 孤荷凌寒自学python第三十九天python 的线程锁Lock

    孤荷凌寒自学python第三十九天python的线程锁Lock (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) 当多个线程同时操作一个文件等需要同时操作某一对象的情况发生时,很有可能发生冲突, ...

  2. Java进阶(三十九)Java集合类的排序,查找,替换操作

    Java进阶(三十九)Java集合类的排序,查找,替换操作 前言 在Java方向校招过程中,经常会遇到将输入转换为数组的情况,而我们通常使用ArrayList来表示动态数组.获取到ArrayList对 ...

  3. Gradle 1.12用户指南翻译——第三十九章. IDEA 插件

    本文由CSDN博客万一博主翻译,其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Githu ...

  4. centos shell编程5 LANMP一键安装脚本 lamp sed lnmp 变量和字符串比较不能用-eq cat > /usr/local/apache2/htdocs/index.php <<EOF重定向 shell的变量和函数命名不能有横杠 平台可以用arch命令,获取是i686还是x86_64 curl 下载 第三十九节课

    centos shell编程5  LANMP一键安装脚本 lamp  sed  lnmp  变量和字符串比较不能用-eq  cat > /usr/local/apache2/htdocs/ind ...

  5. “全栈2019”Java第三十九章:构造函数、构造方法、构造器

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  6. NeHe OpenGL教程 第三十九课:物理模拟

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  7. SQL注入之Sqli-labs系列第三十八关、第三十九关,第四十关(堆叠注入)

    0x1 堆叠注入讲解 (1)前言 国内有的称为堆查询注入,也有称之为堆叠注入.个人认为称之为堆叠注入更为准确.堆叠注入为攻击者提供了很多的攻击手段,通过添加一个新 的查询或者终止查询,可以达到修改数据 ...

  8. 第三百三十九节,Python分布式爬虫打造搜索引擎Scrapy精讲—Scrapy启动文件的配置—xpath表达式

    第三百三十九节,Python分布式爬虫打造搜索引擎Scrapy精讲—Scrapy启动文件的配置—xpath表达式 我们自定义一个main.py来作为启动文件 main.py #!/usr/bin/en ...

  9. WPF,Silverlight与XAML读书笔记第三十九 - 可视化效果之3D图形

    原文:WPF,Silverlight与XAML读书笔记第三十九 - 可视化效果之3D图形 说明:本系列基本上是<WPF揭秘>的读书笔记.在结构安排与文章内容上参照<WPF揭秘> ...

  10. 微信小程序把玩(三十九)navigation API

    原文:微信小程序把玩(三十九)navigation API 演示效果也看到了小程序也就提供这几个处理导航控制.值得注意的是只能同时导航五个页面 主要属性: 导航条一些方法 wx.setNavigati ...

随机推荐

  1. twitter api

    1,twurl安装 1.1,安装软件管理包工具,在管理员身份打开的cmd中执行: @"%SystemRoot%\System32\WindowsPowerShell\v1.0\powersh ...

  2. [BJOI2017]开车

    [BJOI2017]开车 直接做要用栈 修改?难以直接维护 统计边的贡献! len*abs(pre)pre表示前缀car-stop 修改时候,整个区间的pre+1或者-1 分块,块内对pre排序并打标 ...

  3. av_seek_frame() 定位为什么不准呢?

    初次学习和使用ffmpeg,电脑系统有点老,没办法使用最新版的ffmpeg 3.3,只能从别处下载了一个2.8版的用用,官网提供的历史版本都没有我电脑可用的版本. 花了两天时间学习并写了一个简单的处理 ...

  4. 关于递推算法求解约瑟夫环问题P(n,m,k,s)

    一. 问题描述 已知n个人,分别以编号1,2,3,...,n表示,围坐在一张圆桌周围.从编号为k的人开始报数1,数到m的那个人出列:他的下一个人又从1开始报数,数到m的那个人又出列:依此规律重复下去, ...

  5. 第十三节,使用带有全局平均池化层的CNN对CIFAR10数据集分类

    这里使用的数据集仍然是CIFAR-10,由于之前写过一篇使用AlexNet对CIFAR数据集进行分类的文章,已经详细介绍了这个数据集,当时我们是直接把这些图片的数据文件下载下来,然后使用pickle进 ...

  6. python操作excel文件一(xlrd读取文件)

    一般做接口测试,会把参数和一些数据放入excel表中,这样就不会重新编译代码,提高效率.一般如何操作呢?接下来跟着步骤一起学习吧 执行步骤: 1.首先要安装 xlrd这个模块,用 pip instal ...

  7. poj 2566"Bound Found"(尺取法)

    传送门 参考资料: [1]:http://www.voidcn.com/article/p-huucvank-dv.html 题意: 题意就是找一个连续的子区间,使它的和的绝对值最接近target. ...

  8. 安装Androidsdudio时

    安装Androidsdudio时,Androidsdudio的路劲可以任意选择,但Androidsdk的路劲就默认到c盘里.然后安装后就可以直接用了

  9. easyUI,重新渲染

    Easyui中使用jquery或js动态添加元素时出现的样式失效的解决方法 可以使用$.parser.parse();这个方法进行处理: 例如: $.parser.parse(); 表示对整个页面重新 ...

  10. webDriver文档阅读笔记

    一些雷 浏览器版本和对应的Driver的版本是一一对应的,有时候跑不起来,主要是因为driver和浏览器版本对不上. e.g: chrome和driver版本映射表:https://blog.csdn ...