/*封装互斥锁的时候,要用到的方法,20200605*/
//问题一:MutexLock和Condition是否要设计成单例模式?
//     单例模式只能通过该类创建出一个对象,这意味着只能创建一把锁,如果再来一把锁的话,
//      这显然不符合需求,锁可以有多把,条件变量也可以有多个//问题二:MutexLock和Condition的成员是否要设计成static?
//      不能设计成static,否则只能是唯一的//问题三:MutexLock与Condition应该是什么关系?
//       从互斥锁和条件变量的创建以及销毁来看,彼此并不负责对方的生命周期,互不相干,彼此独立
//          由于Condition的接口wait方法是无参的,但是接下来的操作中需要用到互斥锁,MuteLock只能以指针的形式出现在Condition的数据成员中,表达的是一种关联关系(A has B)//问题四:成员变量引用,需要注意构造函数初始化列表中进行// MutexLock 和Condition不能进行复制。class MutexLock
{//先定义接口,再定义实现
public:MutexLock();    //构造函数初始化互斥锁~MutexLock();    //析构函数进行销毁互斥锁 pthread_mutex_destroy(pthread——mutex_t*);void lock();     //phtread_mutex_lockvoid unlock();  //pthread_mutex_unlockpthread_mutex_t *getMutexLockPtr(){  return &_mutex2; }   //返回一个   操作锁private:    //成员放什么//static  pthread_mutex_t  _mutex;          pthread_mutex_t _mutex2;
};class Condition
{public://...Condition();    //  初始化pthread_cond_init(phtread_cond_t*,);~Condition();    // 销毁  pthread_cond_destroy(pthread_cond_t*);void wait();    //   pthread_cond_wait//void wait(MutexLock &mutex);//传参的叫依赖关系--->不调用该函数,彼此是无关的void notify();    //  pthread_cond_signalvoid notifyall();    //  pthread_cond_broadcastprivate://...//pthred_mutex_t * _mutex;//不能,要使用已经封装好的MutexLock//pthread_mutex_t _mutex;//不能,意味着条件变量的对象要负责互斥锁的销毁//MutexLock _mutex;//不能以对象成员的形式出现MutexLock & _mutex;//可以,用引用(指针)都可以的//MutexLock * _mutex;//关联关系(A has  B,彼此并不负责对方生命周期)pthread_cond_t _cond;
};
怎么去设计一个合理的类?面向对象设计 OOD,而不是面向过程
最难的是面向对象设计OOD,学习C++的语法知识是在做OOP
OOD难在对于一个需求或问题进行抽象,分析,为了应对需求的变化。int  pthread_cond_destroy(pthread_cond_t *cond);分为上半部和下半部
使用条件变量的时候一定要调用互斥锁,因为哟啊操作临界资源上半部:当加锁之后,调用该方法时,表示当前线程A要进入阻塞状态,但是在进入阻塞状态之前会解锁下半部:当另外一个线程B调用pthread_cond_signal方法,激活线程A的条件变量,线程A要再往下执行,必须哟啊执行加锁操作,才能往后走,接下来哟啊操作临界资源。
int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex); //内核完成

代码如下:

MutexLock.hpp   Condition.hpp Condition.cc Test.cc Test2.cc Test3.cc

MutexLock.hpp

#ifndef __WD_MUTEXLOCK_H__
#define __WD_MUTEXLOCK_H__#include <pthread.h>
#include <iostream>
using std::cout;
using std::endl;namespace wd
{class MutexLock
{
public:MutexLock(): _isLocking(false){if(0!=pthread_mutex_init(&_mutex,NULL)){perror("pthread_mutex_init");}}//禁止复制控制MutexLock(const MutexLock &)=delete;MutexLock & operator=(const MutexLock &)=delete;~MutexLock() {if(0!=pthread_mutex_destroy(&_mutex)){perror("pthread_mutex_destroy");}}void lock(){if(0!=pthread_mutex_lock(&_mutex)){perror("pthread_mutex_lock");return ;}_isLocking=true;}void unlock(){if(0!=pthread_mutex_unlock(&_mutex)){perror("pthread_mutex_unlock");return ;}_isLocking=false;}pthread_mutex_t *getMutexLockPtr(){//??????return &_mutex;}bool isLocking() const {return _isLocking;}private:pthread_mutex_t _mutex;bool _isLocking;
};class MutexLockGuard
{
public:explicitMutexLockGuard(MutexLock &mutex): _mutex(mutex)//构造函数加锁{_mutex.lock();}~MutexLockGuard()//析构函数来解锁{_mutex.unlock();}private://获取一个互斥锁的对象MutexLock &_mutex;
};}//end of namespace wd#endif

Condition.hpp

#ifndef __WD_CONDITION_H__
#define __WD_CONDITION_H__
#include "MutexLock.hpp"
#include <pthread.h>
#include <iostream>using std::cout;
using std::endl;namespace  wd
{class Condition
{
public:explicitCondition(MutexLock & mutex);~Condition(); //禁止复制?Condition(const Condition &)=delete;Condition &operator=(const Condition &)=delete;void wait();void notify();void notifyAll();private:pthread_cond_t _cond;MutexLock & _mutex;
};}
#endif

Condition.cc


#include "Condition.hpp"
#include <iostream>using std::cout;
using std::endl;namespace wd
{
Condition::Condition(MutexLock & mutex)
: _mutex(mutex)
{if(0!=pthread_cond_init(&_cond,NULL)){perror("pthread_cond_init");}
}Condition:: ~Condition()
{if(0!=pthread_cond_destroy(&_cond)){perror("pthread_cond_destroy");}
}void Condition::wait()
{if(0!=pthread_cond_wait(&_cond,_mutex.getMutexLockPtr())){perror("pthread_cond_wait");}
}
void Condition::notify()
{if(0!=pthread_cond_signal(&_cond)){perror("pthread_cond_signal");}
}void Condition::notifyAll()
{if(0!=pthread_cond_broadcast(&_cond)){perror("pthread_cond_broadcast");}
}}//end of namespace wd

Test1.cc

两个线程抢占式卖票

/*  autor:liulei  */
/*  C++           */
#include "Condition.hpp"
#include <iostream>using std::cout;
using std::endl;struct CriticalResource
{//构造函数完成对象的初始化CriticalResource(long tickets): _tickets(tickets), _mutex(), _cond(_mutex){}long _tickets=1000;wd::MutexLock _mutex;wd::Condition _cond;
};/*1号窗口和2号窗口抢占式的方式卖票*/void *windowsSale1(void *arg)
{cout<<">> windows1: "<<pthread_self()<<endl;CriticalResource *presource=static_cast<CriticalResource*>(arg);while(1){presource->_mutex.lock();if(presource->_tickets>0){presource->_tickets--;cout<<"windows1 left:tickets "<<presource->_tickets<<endl;}else{cout<<"Windows1:tickets has sold out!"<<endl;presource->_mutex.unlock();break;//票卖完的时候,需要退出线程}presource->_mutex.unlock();}return nullptr;
}void *windowsSale2(void *arg)
{cout<<">> windows2: "<<pthread_self()<<endl;CriticalResource *presource=static_cast<CriticalResource*>(arg);while(1){presource->_mutex.lock();if(presource->_tickets>0){presource->_tickets--;cout<<"windows2 left:tickets "<<presource->_tickets<<endl;}else{cout<<"Windows2:tickets has sold out!"<<endl;presource->_mutex.unlock();break;//票卖完的时候,需要退出线程}presource->_mutex.unlock();}return nullptr;
}void test()
{CriticalResource resoure(100000);pthread_t pthid1,pthid2;pthread_create(&pthid1,nullptr,windowsSale1,(void*)&resoure);pthread_create(&pthid2,nullptr,windowsSale2,(void*)&resoure);cout<<"> main thread:"<<pthread_self()<<endl;pthread_join(pthid1,nullptr);pthread_join(pthid2,NULL);
}int main()
{   test();return 0;
}

Test2.cc

两个线程交替卖票

/*  autor:liulei  */
/*  C++           */
#include "Condition.hpp"
#include <iostream>using std::cout;
using std::endl;struct CriticalResource
{CriticalResource()=default;//构造函数完成对象的初始化CriticalResource(long tickets): _tickets(tickets), _mutex(), _cond(_mutex){}long _tickets=1000;bool _flag=false;wd::MutexLock _mutex;wd::Condition _cond{_mutex};
};/*1号窗口和2号窗口交替卖票*/
//1号卖完了通知2号卖,2号卖完了通知1号卖
//  _flag=true,一号卖,否则一号等待
// _flag=flase,二号卖,否则二号等待
void *windowsSale1(void *arg)
{cout<<">> windows1: "<<pthread_self()<<endl;CriticalResource *presource=static_cast<CriticalResource*>(arg);while(1){presource->_mutex.lock();if(presource->_flag==false){presource->_cond.wait();//等待,阻塞}//_flag=true,一号卖票if(presource->_tickets>0){presource->_tickets--;cout<<"windows1 left:tickets "<<presource->_tickets<<endl;//在解锁unlock之前若有其他操作,如执行return,会死锁//一可以采取线程资源清理函数完成//二可以采用C++的方式/* return nullptr;//???? */presource->_mutex.unlock();//通知2号窗口卖票,所以要修改条件presource->_flag=false;presource->_cond.notify();}else{cout<<"Windows1:tickets has sold out!"<<endl;presource->_mutex.unlock();break;//票卖完的时候,需要退出线程}}return nullptr;
}void *windowsSale2(void *arg)
{cout<<">> windows2: "<<pthread_self()<<endl;CriticalResource *presource=static_cast<CriticalResource*>(arg);while(1){presource->_mutex.lock();if(presource->_flag==true){presource->_cond.wait();}//2.2 _flag 为false的时候,执行卖票操作   if(presource->_tickets>0){presource->_tickets--;cout<<"windows2 left:tickets "<<presource->_tickets<<endl;presource->_mutex.unlock();presource->_flag=true;presource->_cond.notify();}else{cout<<"Windows2:tickets has sold out!"<<endl;presource->_mutex.unlock();break;//票卖完的时候,需要退出线程}}return nullptr;
}void test()
{CriticalResource resoure(100000);pthread_t pthid1,pthid2;pthread_create(&pthid1,nullptr,windowsSale1,(void*)&resoure);pthread_create(&pthid2,nullptr,windowsSale2,(void*)&resoure);cout<<"> main thread:"<<pthread_self()<<endl;pthread_join(pthid1,nullptr);pthread_join(pthid2,nullptr);
}int main()
{   test();return 0;
}

Test3.cc

两个线程卖票,可以用C++去解决解锁之前出现的死锁问题

/*  autor:liulei  */
/*  C++           */
#include "Condition.hpp"
#include <iostream>using std::cout;
using std::endl;struct CriticalResource
{CriticalResource()=default;//构造函数完成对象的初始化CriticalResource(long tickets): _tickets(tickets), _mutex(), _cond(_mutex){}long _tickets=1000;bool _flag=false;wd::MutexLock _mutex;wd::Condition _cond{_mutex};
};/*1号窗口和2号窗口交替卖票*/
//1号卖完了通知2号卖,2号卖完了通知1号卖
//  _flag=true,一号卖,否则一号等待
// _flag=flase,二号卖,否则二号等待
void *windowsSale1(void *arg)
{cout<<">>>> windows1: "<<pthread_self()<<endl;CriticalResource *presource=static_cast<CriticalResource*>(arg);while(1){/* presource->_mutex.lock(); */wd::MutexLockGuard mlg(presource->_mutex);if(presource->_flag==false){presource->_cond.wait();//等待,阻塞}//_flag=true,一号卖票if(presource->_tickets>0){presource->_tickets--;cout<<"windows1 left:tickets "<<presource->_tickets<<endl;//在解锁unlock之前若有其他操作,如执行return,会死锁//一可以采取线程资源清理函数完成//二可以采用C++的方式return nullptr;//????/* presource->_mutex.unlock(); *///通知2号窗口卖票,所以要修改条件presource->_flag=false;presource->_cond.notify();}else{cout<<"Windows1:tickets has sold out!"<<endl;/* presource->_mutex.unlock(); */break;//票卖完的时候,需要退出线程}}return nullptr;
}void *windowsSale2(void *arg)
{cout<<"windows2: "<<pthread_self()<<endl;CriticalResource *presource=static_cast<CriticalResource*>(arg);while(1){/* presource->_mutex.lock(); */wd::MutexLockGuard mlg(presource->_mutex);if(presource->_flag==true){presource->_cond.wait();}//2.2 _flag 为false的时候,执行卖票操作   if(presource->_tickets>0){presource->_tickets--;cout<<"windows2 left:tickets "<<presource->_tickets<<endl;presource->_flag=true;presource->_cond.notify();}else{cout<<"Windows2:tickets has sold out!"<<endl;/* presource->_mutex.unlock(); */break;//票卖完的时候,需要退出线程}}return nullptr;
}void test()
{CriticalResource resoure(100000);pthread_t pthid1,pthid2;pthread_create(&pthid1,nullptr,windowsSale1,(void*)&resoure);pthread_create(&pthid2,nullptr,windowsSale2,(void*)&resoure);cout<<"> main thread:"<<pthread_self()<<endl;pthread_join(pthid1,nullptr);pthread_join(pthid2,nullptr);
}int main()
{   test();return 0;
}

用C++ 封装linux下的互斥锁MutexLock和条件变量Condition相关推荐

  1. 专科 java转go 翱翔之路(四)协议通信 锁,互斥锁 读写锁 条件变量锁 连接mysql 查询

    2.7.5 2.7.5.1 协议通信过程 应用层 hello 传输层(udp tcp) 源port 目的端口 hello 网络层(ip) 源ip 目的ip 源port 目的端口 hello 链路层(m ...

  2. linux之mutex(互斥锁)

    在Posix Thread中定义有一套专门用于线程同步的mutex函数 1. 创建和销毁 有两种方法创建互斥锁,静态方式和动态方式.POSIX定义了一个宏PTHREAD_MUTEX_INITIALIZ ...

  3. Linux下sed命令替换配置文件中某个变量的值(改变包含字符的一行的值)之二——只改变第一出现的那一行

    一.背景 在之前的文章中有介绍过<Linux下sed命令替换配置文件中某个变量的值(改变包含字符的一行的值)> 但是这种方法存在一定的问题,就是假如某个变量在一个文件中出现两次,却只想更改 ...

  4. linux 怎么添加path环境变量,Linux下怎么添加和查看PATH环境变量

    linux下查看和添加PATH环境变量 来自:http://apps.hi.baidu.com/share/detail/32942984 $PATH:决定了shell将到哪些目录中寻找命令或程序,P ...

  5. linux env 变量,Linux下 输入 env 而得到的环境变量解读

    HOSTNAME=Master.Hadoop MAHOUT_HOME=/usr/hadoop/mahout-distribution-0.8 TERM=linux SHELL=/bin/bash HA ...

  6. linux C语言多线程库pthread中条件变量的正确用法逐步详解

    linux C语言多线程库pthread中条件变量的正确用法: 了解pthread常用多线程API和pthread互斥锁,但是对条件变量完全不知道或者不完全了解的人群. 关于条件变量的典型应用,可以参 ...

  7. Linux学习之系统编程篇:条件变量(pthread_cond_init / wait / signal / broadcast / destroy)

    一.条件变量的认识 (1)条件变量的引出: 各个线程访问共享资源,比如说共享资源是一个空资源,那么,各线程的访问其实都是无效访问,因此需要一个机制,首先阻塞线程,以免其错误访问,待条件满足时(比如 共 ...

  8. linux线程(互斥锁、条件)

    线程概念: 典型的UNIX/Linux进程可以看成只有一个控制线程:一个进程在同一时刻只做一件事情.有了多个控制线程后,在程序设计时可以把进程设计成在同一时刻做不止一件事,每个线程各自处理独立的任务. ...

  9. linux 信号量锁 内核,Linux内核信号量互斥锁应用

    主要介绍了Linux 内核关于信号量,互斥锁等的应用 内核同步机制-信号量/互斥锁/读-写信号量 sema ,mutex ,rwsem 信号量 通用信号量 用户类进程之间使用信号量(semaphore ...

最新文章

  1. 【Flutter】Image 组件 ( 配置本地 gif 图片资源 | 本地资源加载 placeholder )
  2. java线程通信概念_java基础线程总结(线程概念、线程创建方式、线程间通信、线程重要方法)...
  3. 搭建简易Linux局网服务器
  4. Spring Security与Maven教程
  5. C++学习之路 | PTA乙级—— 1020 月饼 (25分)(带注释)(精简)
  6. 用aliplayer如何实现视频的连续播放?
  7. 同程旅行王晓波:如何改变 Redis 用不好的误区
  8. java数组 规定数量_java – 如何在数组中保持不同事物的数量?
  9. ios与android设备即时语音互通的录音格式预研说明
  10. 小学计算机键盘的初步认识教案,教学设计——小小键盘真神奇
  11. Bridge的VLAN接口模式
  12. ROS路径规划(全局路径规划)
  13. 安卓开发之WebView的使用
  14. 利用jspx解决jsp后缀被限制拿shell
  15. MATLAB强化学习实战(三) 使用并行计算训练DQN智能体进行车道保持辅助(LKA)
  16. FOI对象中显示labels --Oracle Map
  17. 2022-2028年全球及中国点胶枪行业发展现状调研及投资前景分析
  18. 解决Number of partitions scanned (=2001) on table ‘tablexx‘ exceeds limit (=2000)
  19. 面对工业4.0,我国工业企业的挑战与对策
  20. JAVA生成带图片带名称的二维码

热门文章

  1. monodepth2 理解
  2. ppt中如何合并流程图_简单4招,教你轻松搞定PPT中的流程图!
  3. dfs 个人理解总结
  4. 涉密磁介质数据清除工具
  5. 环形数组队列求滑动窗口最大值
  6. (翻译)可变形控件(Morphing Controls)
  7. 数据预处理,PCA主成分分析
  8. 外商投资产业指导目录(2007年修订)
  9. PNAS:人类、非人灵长类动物和小鼠的大脑皮层折叠、分割和连通性
  10. redis连接数合理配置_redis连接数配置多少