当前位置: 首页 > news >正文

做列表的网站wordpress易语言登录

做列表的网站,wordpress易语言登录,网站定制合同和模版的区别,百度搜索智能精选目录 一、线程互斥1.1相关概念介绍1.2互斥量mutex1.3互斥量接口1.3.1初始化互斥量1.3.2销毁互斥量1.3.3互斥量加锁1.3.4互斥量解锁1.3.5使用互斥量解决上面分苹果问题 1.4互斥原理 二、可重入与线程安全2.1相关概念2.2常见线程不安全的情况2.3常见不可重入的情况2.4 可重入与线… 目录 一、线程互斥1.1相关概念介绍1.2互斥量mutex1.3互斥量接口1.3.1初始化互斥量1.3.2销毁互斥量1.3.3互斥量加锁1.3.4互斥量解锁1.3.5使用互斥量解决上面分苹果问题 1.4互斥原理 二、可重入与线程安全2.1相关概念2.2常见线程不安全的情况2.3常见不可重入的情况2.4 可重入与线程安全的关系 三、死锁四、线程同步4.1同步概念与竞态条件4.2条件变量4.2.1概念4.2.2接口4.2.2.1初始化条件变量4.2.2.2销毁条件变量4.2.2.2等待条件变量满足4.2.2.3唤醒等待4.2.2.5改进分苹果 一、线程互斥 1.1相关概念介绍 临界资源 多线程执行流共享的资源叫做临界资源临界区 每个线程内部访问临界资源的代码被称为临界区互斥 任何时刻互斥保证有且只有一个执行流进入临界区访问临界资源通常对临界资源起保护作用原子性 不会被任何调度机制打断的操作该操作只有两态要么完成要么未完成 为什么要有线程互斥下面模拟下4人分苹果的代码。 代码 #includeiostream using namespace std; #includepthread.h #includestring #includevector #includeunistd.h const int NUM4; class ThreadDate { public: ThreadDate(string name){_namename;}string _name; }; int Apples100; void* GetApple(void* args) {ThreadDate* tdstatic_castThreadDate*(args);while(1){if(Apples0){sleep(1);couttd-_nameget a apple,apple number--Applesendl;}else break;}return nullptr; } int main() {vectorpthread_t tids;vectorThreadDate* tds;for(int i0;iNUM;i){string namethreadto_string(i);ThreadDate* tdnew ThreadDate(name);tds.push_back(td);pthread_t tid;pthread_create(tid,nullptr,GetApple,tds[i]);tids.push_back(tid);}for(int i0;iNUM;i){pthread_join(tids[i],nullptr);delete tds[i];}return 0; }现象 产生该现象的原因 1.2互斥量mutex 若线程使用的数据是局部变量变量的地址空间在线程栈空间内变量归属单个线程其他线程无法获得这种变量但有些变量需要在线程间共享共享变量可以通过数据的共享完成线程之间的交互。多个线程并发的操作共享变量就会带来一些问题 要解决上述分苹果的问题需要做到三点 代码必须有互斥行为当代码进入临界区执行时不允许其他线程进入该临界区。 若多个线程同时要求执行临界区的代码并且此时临界区没有线程在执行那么只能允许一个线程进入该临界区 若线程不在临界区中执行那么该线程不能阻止其他线程进入临界区 这时就需要一把锁Linux中提供的这把锁被称为互斥量 1.3互斥量接口 1.3.1初始化互斥量 int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);参数 mutex需要初始化的互斥量的地址attr初始化互斥量的属性一般设置为nullptr即可 返回值互斥量初始化成功返回0失败返回错误码 使用pthread_mutex_init()函数初始化互斥量的方式被称为动态分配还可以使用静态分配进行初始化即下面这种方式 pthread_mutex_t mutex PTHREAD_MUTEX_INITIALIZER;1.3.2销毁互斥量 int pthread_mutex_destroy(pthread_mutex_t *mutex);参数mutex需要销毁的互斥量的地址 返回值互斥量销毁成功返回0失败返回错误码 注意 使用PTHREAD_MUTEX_INITIALIZER初始化的互斥量不需要销毁不要销毁一个已经加锁的互斥量已经销毁的互斥量要确保后面不会有线程再尝试加锁 1.3.3互斥量加锁 int pthread_mutex_lock(pthread_mutex_t *mutex);参数mutex需要加锁的互斥量的地址 返回值互斥量加锁成功返回0失败返回错误码 注意 互斥量处于未锁状态时该函数会将互斥量锁定同时返回成功发起函数调用时若其他线程已经锁定互斥量或者存在其他线程同时申请互斥量但没有竞争到互斥量那么线程会在pthread_mutex_lock()函数内部阻塞至互斥量解锁 1.3.4互斥量解锁 int pthread_mutex_unlock(pthread_mutex_t *mutex);参数mutex需要解锁的互斥量的地址 返回值互斥量解锁成功返回0失败返回错误码 1.3.5使用互斥量解决上面分苹果问题 #includeiostream using namespace std; #includepthread.h #includestring #includevector #includeunistd.h const int NUM4; class ThreadDate { public: ThreadDate(string name,pthread_mutex_t* lock){_namename;_locklock;} public:string _name;pthread_mutex_t* _lock;}; int Apples100; void* GetApple(void* args) {ThreadDate* tdstatic_castThreadDate*(args);while(1){pthread_mutex_lock(td-_lock);if(Apples0){//sleep(1);couttd-_nameget a apple,apple numberApples--endl;pthread_mutex_unlock(td-_lock);}else {pthread_mutex_unlock(td-_lock);break;}}return nullptr; } int main() {pthread_mutex_t lock;pthread_mutex_init(lock,nullptr);vectorpthread_t tids;vectorThreadDate* tds;for(int i0;iNUM;i){string namethreadto_string(i);ThreadDate* tdnew ThreadDate(name,lock);tds.push_back(td);pthread_t tid;pthread_create(tid,nullptr,GetApple,tds[i]);tids.push_back(tid);}for(int i0;iNUM;i){pthread_join(tids[i],nullptr);delete tds[i];}pthread_mutex_destroy(lock);return 0; }写这个代码的时候出现了一个乌龙。写到这里复盘以下顺便提一嘴多线程写代码时考虑的是要多一点。 1.4互斥原理 引入互斥量后当一个线程申请到锁进入临界区时在其他线程看来该线程只有两种状态要么没有申请锁要么锁已经释放了因为只有这两种状态对其他线程才是有意义的。 例如图中线程1进入临界区后在线程2、3、4看来线程1要么没有申请锁要么线程1已经将锁释放了因为只有这两种状态对线程2、3、4才是有意义的当线程2、3、4检测到其他状态(线程1持有锁)时也就被阻塞了。此时对于线程2、3、4而言线程1的整个操作过程是原子的 临界区内的线程可能被切换吗 临界区内的线程是可能进行线程切换。但即便该线程被切走其他线程也无法进入临界区进行资源访问因为此时该线程是拿着锁被切走的锁没有被释放也就意味着其他线程无法申请到锁也就无法进入临界区进行资源访问了。 互斥锁是否需要被保护 既然锁是临界资源那么锁就必须被保护起来但锁本身就是用来保护临界资源的那锁又由谁来保护的呢 锁实际上是自己保护自己的只需要保证申请锁的过程是原子的那么锁就是安全的 如何保证申请锁是原子的 为了实现互斥锁操作大多数体系结构都提供了swap或exchange指令该指令的作用就是把寄存器和内存单元的数据相交换。由于只有一条指令保证了原子性。 lock和unlock的伪代码 二、可重入与线程安全 2.1相关概念 线程安全 多个线程并发同一段代码时不会出现不同的结果重入同一个函数被不同的执行流调用当前一个流程还没有执行完就有其他的执行流再次进入称之为重入。一个函数在重入的情况下运行结果不会出现任何不同或者任何问题则该函数被称为可重入函数否则是不可重入函数。 2.2常见线程不安全的情况 不保护共享变量的函数函数状态随着被调用状态发生变化的函数返回指向静态变量指针的函数调用线程不安全函数的函数 2.3常见不可重入的情况 调用了malloc/free函数因为malloc函数是用全局链表来管理堆的调用了标准I/O库函数标准I/O可以的很多实现都是以不可重入的方式使用全局数据结构函数体内使用了静态的数据结构 2.4 可重入与线程安全的关系 线程安全不一定是可重入的而可重入函数则一定是线程安全的可重入函数是线程安全函数的一种函数是不可重入的那就不能由多个线程使用有可能引发线程安全问题若一个函数中有全局变量那么这个函数既不是线程安全也不是可重入的若对临界资源的访问加上锁则这个函数是线程安全的但如果这个重入函数的锁还未释放则会产生死锁因此是不可重入的 三、死锁 死锁是指在一组进程中的各个进程均占有不会释放的资源但因互相申请被其他进程所占用不会释放的资源而处于的一种永久等待状态 一个锁锁死 多个锁锁死 线程A申请锁资源的顺序为锁1、锁2线程B申请锁资源的顺序为锁2、锁1 当线程A申请到锁1准备申请锁2时线程B已申请到锁2准备申请锁1这时两个线程都会因为申请锁失败而陷入阻塞并且无法释放锁进入死锁状态 产生死锁的条件 互斥条件 一个资源每次只能被一个执行流使用请求与保持条件 一个执行流因请求资源而阻塞时对已获得的资源保持不放不剥夺条件 一个执行流已获得的资源在未使用完之前不能强行剥夺循环等待条件 若干执行流之间形成一种头尾相接的循环等待资源的关系 避免死锁破坏死锁的四个必要条件加锁顺序一致避免锁未释放的场景资源一次性分配 四、线程同步 4.1同步概念与竞态条件 同步 在保证数据安全的前提下让线程能够按照某种特定的顺序访问临界资源从而有效避免饥饿问题这就叫做同步 竞态条件 因为时序问题而导致程序异常我们称之为竞态条件 单纯的加锁是会存在某些问题的若某个线程的优先级较高或竞争力较强每次都能够申请到锁但申请到锁之后什么也不做那么这个线程就一直在申请锁和释放锁这就可能导致其他线程长时间竞争不到锁引起饥饿问题单纯的加锁是没有错的它能够保证在同一时间只有一个线程进入临界区但它没有高效的让每一个线程使用这份临界资源现在增加一个规则当一个线程释放锁后这个线程不能立马再次申请锁该线程必须排到这个锁的资源等待队列的最后增加这个规则之后下一个获取到锁的资源的线程就一定是在资源等待队列首部的线程若有十个线程就能够让这十个线程按照某种次序进行临界资源的访问 4.2条件变量 4.2.1概念 条件变量是利用线程间共享的全局变量进行同步的一种机制条件变量是用来描述某种资源是否就绪的一种数据化描述 条件变量主要包括两个动作 一个线程等待条件变量的条件成立而被挂起另一个线程使条件成立后唤醒等待的线程 条件变量通常需要配合互斥锁一起使用 4.2.2接口 4.2.2.1初始化条件变量 int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);参数 cond需要初始化的条件变量的地址attr初始化条件变量的属性一般设置为NULL即可 返回值条件变量初始化成功返回0失败返回错误码 使用pthread_cond_init()函数初始化条件的方式被称为动态分配还可以使用静态分配进行初始化即下面这种方式 pthread_cond_t cond PTHREAD_COND_INITIALIZER;4.2.2.2销毁条件变量 int pthread_cond_destroy(pthread_cond_t *cond);参数cond需要销毁的条件变量的地址 返回值条件变量销毁成功返回0失败返回错误码 注意使用PTHREAD_COND_INITIALIZER初始化的条件变量不需要销毁 4.2.2.2等待条件变量满足 int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);参数 cond需要等待的条件变量的地址mutex当前线程所处临界区对应的互斥锁 返回值函数调用成功返回0失败返回错误码 4.2.2.3唤醒等待 int pthread_cond_broadcast(pthread_cond_t *cond); int pthread_cond_signal(pthread_cond_t *cond);pthread_cond_signal()函数用于唤醒该条件变量等待队列中首个线程pthread_cond_broadcast()函数用于唤醒该条件变量等待队列中的全部线程 参数cond唤醒在cond条件变量下等待的线程 返回值函数调用成功返回0失败返回错误码 4.2.2.5改进分苹果 #includeiostream using namespace std; #includepthread.h #includestring #includevector #includeunistd.h const int NUM4;pthread_cond_t condPTHREAD_COND_INITIALIZER;class ThreadDate { public: ThreadDate(string name,pthread_mutex_t* lock){_namename;_locklock;} public:string _name;pthread_mutex_t* _lock;}; int Apples10; int flagNUM; void* GetApple(void* args) {ThreadDate* tdstatic_castThreadDate*(args);while(1){pthread_mutex_lock(td-_lock);pthread_cond_wait(cond,td-_lock);//线程在等待队列的时候会自动释放锁if(Apples0){couttd-_nameget a apple,apple numberApples--endl;pthread_mutex_unlock(td-_lock);}else {pthread_mutex_unlock(td-_lock);break;}}couttd-_name quit!endl;pthread_mutex_lock(td-_lock);pthread_cond_wait(cond,td-_lock);flag--;pthread_mutex_unlock(td-_lock);return nullptr; } int main() {pthread_mutex_t lock;pthread_mutex_init(lock,nullptr);vectorpthread_t tids;vectorThreadDate* tds;for(int i0;iNUM;i){string namethreadto_string(i);ThreadDate* tdnew ThreadDate(name,lock);tds.push_back(td);pthread_t tid;pthread_create(tid,nullptr,GetApple,tds[i]);tids.push_back(tid);}sleep(3);while(flag){pthread_cond_signal(cond);sleep(1);}for(int i0;iNUM;i){pthread_join(tids[i],nullptr);delete tds[i];}pthread_mutex_destroy(lock);pthread_cond_destroy(cond);return 0; }
http://www.zqtcl.cn/news/177789/

相关文章:

  • 网站开发老板排名关键词优化师
  • 迈诺网站建设跨境电商平台网站建设
  • 做t恤的网站外贸仿牌网站建设
  • 网站建设的学习网站建站后维护需要做哪些
  • 为什么建设网站很多公司没有网站界面分析
  • 旅游网网站建设的管理大连淘宝网站建设
  • 无锡锡牛网站建设做汽配的外贸网站
  • 黄石公司做网站临湘做网站
  • 网站配色购物网站开发背景需求
  • 河北省建设工程教育网站如何在手机上制作app软件
  • 担保公司网站建设汇报wordpress修改默认域名
  • 网站平台建设需要多少钱html网站标题怎么做的
  • 国外的服务器网站wordpress 博客论坛
  • 多国语言网站模板修改wordpress登录密码
  • 给周杰伦做网站广州免费景点
  • 网站文章不显示淄博网站建设及托管
  • 国外免费建站平面广告设计案例
  • 微信微网站开发价格广西做网站的公司有哪些
  • 做网站内容哪家公司可以做网站
  • 网站后台数据库管理经常浏览不良网站会被记录吗
  • 做加工都在哪个网站推广网络营销外包推广
  • 做英文网站怎么赚钱经典logo设计案例分析
  • 大型建站公司是干嘛的wordpress激活码充值
  • 带后台网站模板wordpress注册模板
  • 济南城乡住房建设厅网站dedecms企业网站
  • 旅游网站怎么做才能被关注园林景观设计公司名字
  • 建站之星网站建设系统事业单位网站登录模板
  • 如何做京东优惠券网站建设银行网站储蓄账户查询密码
  • 月付购物网站建站方维网络科技有限公司
  • 广东外贸网站建设企业手写代码网站