多线程-----ATM存取钱

本文通过一个银行账户存取款的例子介绍了多线程环境下数据竞争问题,并演示了如何使用互斥锁来确保数据的一致性和安全性。
首先博主和大家聊一聊多线程吧。多线程这个东西是后于C++出现的,所以很多学习C++的童鞋在很久之后才能明白什么叫多线程。其实多线程这个东西吧,其实真的很恶心。在我看来,如果不用多线程的话最好不要用,因为这个调试,什么线程互锁之类的,你真的是有点hold不住的。但是,在一些情况下,你又不得不使用多线程。比如说什么情况呢?通常情况下,异步处理是需要进行多线程的。比如说聊天程序。一般情况下,聊天的同时是可能要发送文件之类的。这个时候就比较蛋疼了,如果只有一个程序,我怎么处理发送文件这个事件?再比如说,我要接收一个文件,那么如果我这只有一个主进程的话,我难道主进程什么都不干就这样干等着你?如果说这个时候就需要多线程去处理触发性事件或者是挂起等待了。
但是,多线程的问题确实很麻烦,今天我就和大家说一个比较基础的案例吧。如果说,每一个消费者都是一个对象,然后这个对象里面是有自己的存款。但是,每一个消费者都不只一个途径去进行存取款。比如,你有一张银行账号,一个主卡一个副卡。主卡在你手里,副卡在你妈妈手里。有一天你的卡上还剩10块钱,所以你妈妈打钱给你。在同一时刻,你和你妈妈对账户进行操作,你取一块钱,你妈妈存100块。这个时候系统开两个线程处理这个事情。但是由于某些原因,取钱的处理时间比存钱的长,于是乎你的账户:首先你们两都读取自己的余额,10元。然后你取1元,还剩9元,你妈妈存钱,还剩110(因为你妈妈的现场读取出来的余额是开始的10元,不是9元)。然后你的线程出了点问题,延时了一段时间。这个时候,你妈妈存钱的余额先返回,余额是110元,但是当你的线程返回的时候,又变成9元了。搞到最后,你还是一毛钱都没有。。。。。。。。。。。。。。。。。。。。。。。。。。。。所以说,如果你的银行卡的钱一直在减少一定是哪个sb程序员写的代码有问题,,,,,嗯,我一直是这么觉得的。
好了,言归正传。
一般情况下,很多事情虽然需要多线程,但是关键数据都是需要单线程的,因为错了真的是负责不起。
所以需要锁定互斥,让关键数据处理的地方无论如何只能一个线程处理。
好了,上代码。
这里,博主用的是boost的thread库,希望大家可以多学习学习boost库里面的用法。
// blog_thread_mutex.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#define BOOST_HAS_WINTHREADS
#define BOOST_THREAD_BUILD_DLL
#define BOOST_DATE_TIME_SOURCE
#define BOOST_THREAD_NO_LIB
//#define BOOST_THREAD_USE_LIB 

#include
extern "C" void tss_cleanup_implemented(void){}
#include
#include
#include
#include
#include
#include
#include
#include
class consumer:boost::noncopyable
{
private:
boost::mutex mutex_money;//这里定义两个互斥量一个事数据互斥,一个事io互斥。数据互斥相信大家会理解,但是为什么要用io互斥呢?主要在于std::cout并不是一个安全的线程,所以如果多线程输出,还是要设置io互斥量
boost::mutex io_mutex;
size_t money;
public:
consumer(size_t _money=0):money(_money)
{
boost::mutex::scoped_lock lock_io(io_mutex);
std::cout<<"now you have "<<money<<std::endl;
}
void consumer_deposit(int var)
{
boost::mutex::scoped_lock lock_money(mutex_money);
money+=var;
boost::mutex::scoped_lock lock_io(io_mutex);
std::cout<<"you have deposited "<<var<<". now you have "<<money<<std::endl;
}
void sonsumer_withdraw(int var)
{
    boost::mutex::scoped_lock lock_money(mutex_money);
money-=var;
boost::mutex::scoped_lock lock_io(io_mutex);
std::cout<<"you have withdraw "<<var<<". now you have "<<money<<std::endl;
}



};
int main()
{
consumer new_consumer(100);
auto fun_deposit=boost::bind(&consumer::consumer_deposit,boost::ref(new_consumer),_1);//这里用的是回调函数,bind是函数绑定,_1是一个占位符,意思是重载第一个参数
auto fun_withdraw=boost::bind(&consumer::sonsumer_withdraw,boost::ref(new_consumer),_1);
//这里模拟了6次存取,但是数据的存取和io不会发生多线程同时操作的错误
boost::thread   thread1(fun_deposit,10);
boost::thread   thread4(fun_withdraw,30);
boost::thread   thread2(fun_deposit,20);
boost::thread   thread5(fun_withdraw,40);
boost::thread   thread3(fun_deposit,30);
boost::thread   thread6(fun_withdraw,50);
thread1.join();
thread2.join();
thread3.join();
thread4.join();
thread5.join();
thread6.join();

return 0;
}
运行结果:
多线程-----ATM存取钱




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值