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

宁乡网站建设济南品牌网站制作便宜

宁乡网站建设,济南品牌网站制作便宜,做网站有什么用出,新竹网站目录 一、问题引入 二、实现线程同步的方案——条件变量 1、常用接口&#xff1a; 2、使用示例 一、问题引入 我们再次看看上次讲到的多线程抢票的代码&#xff1a;这次我们让一个线程抢完票之后不去做任何事。 #include <iostream> #include <unistd.h> #inc…

目录

一、问题引入

二、实现线程同步的方案——条件变量

1、常用接口:

2、使用示例


一、问题引入

我们再次看看上次讲到的多线程抢票的代码:这次我们让一个线程抢完票之后不去做任何事。

#include <iostream>
#include <unistd.h>
#include <cstring>
#include <time.h>
#include <pthread.h>using namespace std;
#define THREAD_NUM 5class threaddata
{
public:threaddata(const string &s, pthread_mutex_t *m): name(s), mtx(m){}public:string name;pthread_mutex_t *mtx;
};int ticket = 100;void *getticket(void *arg)
{threaddata *td = (threaddata *)arg;while (true){pthread_mutex_lock(td->mtx); if (ticket > 0)              {usleep(rand() % 10000);cout << td->name << ":"<< " " << ticket << endl;ticket--;pthread_mutex_unlock(td->mtx); }else{pthread_mutex_unlock(td->mtx); break;}}delete td;return nullptr;
}int main()
{pthread_mutex_t mtx;pthread_mutex_init(&mtx, nullptr);pthread_t t[THREAD_NUM];for (int i = 0; i < THREAD_NUM; i++){string name = "thread ";name += to_string(i + 1);threaddata *td = new threaddata(name, &mtx);pthread_create(t + i, nullptr, getticket, (void *)td);}for (int i = 0; i < THREAD_NUM; i++)pthread_join(t[i], nullptr);pthread_mutex_destroy(&mtx);return 0;
}

运行结果:

我们这就发现了一个问题,对于抢票系统,我们看到的是只有一个线程5在一直连续抢票,没有其他的线程。这很不合理。

这是因为如果个别线程的竞争力特别强,每次都能够申请到锁,但申请到锁之后什么也不做,所以在我们看来这个线程就一直在申请锁和释放锁,那么它就可以一直抢票。这就可能导致其他线程长时间竞争不到锁,造成了其他线程的饥饿问题(无法抢票)。虽然,你是拿到锁后再去访问临界资源,并且最后还释放了锁,由于竞争能力太强,可以一直拿到锁,这没有错,但这不合理。

为了解决这个问题,我们增加一个限制:当一个线程释放锁后,这个线程不能立马再次申请锁,该线程必须排到这个锁的资源等待队列的最后。这样,我们就有了线程同步:我们在保证数据安全的情况下让这些线程按照一定的顺序进行临界资源的访问,这就是线程同步。

竞态条件:因为时序问题,而导致程序异常,我们称为竞态条件。

二、实现线程同步的方案——条件变量

当一个线程互斥地访问某个变量时,它可能发现在其他线程改变状态之前,它什么也做不了

例如一个线程访问队列时,发现队列为空,它只能等待,直到其他线程将一个节点添加到队列中。这种情况就需要用到条件变量。

1、常用接口:

1、条件变量的定义和初始化

​
NAMEpthread_cond_destroy, pthread_cond_init - destroy and initialize condition variablesSYNOPSIS#include <pthread.h>//销毁int pthread_cond_destroy(pthread_cond_t *cond);//初始化int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *restrict attr);//全局和静态变量初始化pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

2、线程等待临界资源: 

pthread_cond_wait 功能:一就是让线程在特定的条件变量下等待,二就是让线程在等待时释放对应的互斥锁。当线程被唤醒时,该函数会帮助我们线程获取锁。

#include <pthread.h>
//特定时间阻塞等待
int pthread_cond_timedwait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex,const struct timespec *restrict abstime);
//等待
int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex);

 3、唤醒线程去访问临界资源

#include <pthread.h>
// 唤醒所有等待的线程
int pthread_cond_broadcast(pthread_cond_t *cond);// 唤醒一个线程
int pthread_cond_signal(pthread_cond_t *cond);

注:1、条件变量通常需要配合互斥锁一起使用。

2、条件变量的使用:一个线程等待条件变量的条件成立而被挂起;另一个线程使条件成立后唤醒等待的线程。

3、等待的时候往往是在临界区内等待的。(加锁与解锁之间的区域进行等待)

4、线程被唤醒,是在之前进行等待的地方被唤醒。

2、使用示例

有了线程同步,我们就可以改进我们之前的抢票系统的代码:

#include <iostream>
#include <string>
#include <time.h>
#include <unistd.h>
#include <pthread.h>using namespace std;
#define THREADNUM 3
typedef void *(*func)(void *argc);class threaddata
{
public:threaddata(pthread_mutex_t *mtx, pthread_cond_t *cond, const string &name): mtx_(mtx), cond_(cond), name_(name){}public:pthread_mutex_t *mtx_;pthread_cond_t *cond_;string name_;
};int ticket = 100;void *getticket(void *arg)
{threaddata *td = (threaddata *)arg;while (true){pthread_mutex_lock(td->mtx_);pthread_cond_wait(td->cond_, td->mtx_); // 在加锁和解锁之间进行等待if (ticket > 0){usleep(rand() % 10000);cout << td->name_ << ":"<< " " << ticket << endl;ticket--;pthread_mutex_unlock(td->mtx_);}else{pthread_mutex_unlock(td->mtx_);break;}}delete td;return nullptr;
}void *fun1(void *arg)
{threaddata *td = (threaddata *)arg;while (true){getticket((void *)td);sleep(1);}
}void *fun2(void *arg)
{threaddata *td = (threaddata *)arg;while (true){getticket((void *)td);sleep(1);}
}void *fun3(void *arg)
{threaddata *td = (threaddata *)arg;while (true){getticket((void *)td);sleep(1);}
}int main()
{srand((unsigned long)time(nullptr) ^ getpid() ^ 433);pthread_mutex_t mtx;pthread_cond_t cond;pthread_mutex_init(&mtx, nullptr);pthread_cond_init(&cond, nullptr);pthread_t t[THREADNUM];func fun[THREADNUM] = {fun1, fun2, fun3};for (int i = 0; i < THREADNUM; i++){string name = "thread ";name += to_string(i + 1);threaddata *td = new threaddata(&mtx, &cond, name);pthread_create(t + i, nullptr, fun[i], (void *)td);}sleep(5);while (true){pthread_cond_signal(&cond);sleep(1);}for (int i = 0; i < THREADNUM; i++)pthread_join(t[i], nullptr);pthread_mutex_destroy(&mtx);pthread_cond_destroy(&cond);return 0;
}

如果我们每次都想将在该条件变量下等待的所有线程进行唤醒,可以将代码中的pthread_cond_signal函数改为pthread_cond_broadcast函数。 

此时我们会发现唤醒这三个线程时具有明显的顺序性,因为这些线程启动时默认都会在该条件变量下去等待,而我们每次都唤醒的是在当前条件变量下等待的头部线程,当该线程执行完代码后会继续排到等待队列的尾部进行等待。

http://www.yayakq.cn/news/145478/

相关文章:

  • 新开神途手游发布网站产品画册设计公司
  • 网站备案查询官网游戏开发软件免费下载
  • 网站前置或专项审批地方网站类型
  • 网站建设 英汇网络苏州工业园区劳动局网站做不了合同
  • 备案的域名可以做盗版电影网站吗widows安装wordpress
  • 东莞网站建设推广哪家好深圳外贸公司集中在哪
  • 贵南县网站建设公司东莞沙田网站建设
  • 网站改版 网站存在问题cms免费建站系统
  • 广州关键词优化外包硬件优化大师
  • 怎样做自己的公司网站做一个人网站需要注意什么
  • 班级网站怎么做长沙建站网
  • 吉林省建设厅证件查询网站江苏建设教育网首页
  • 门户网站内容建设岗位职责网站突然被降权怎么办
  • 合肥网站建设优化学习彩页设计公司
  • 怎样做淘宝的导购网站推广ppt模板设计
  • 网站后台密码怎么修改提交链接
  • 网站宽屏版模板制作视频
  • 中国建设集团门户网做网站建设优化的公司
  • 灯光设计网站推荐wordpress sdk.js好卡
  • 桂阳城乡建设局网站wordpress 页面显示最新文章
  • it外包范围北京企业网站seo
  • 与市场营销有关的网站科技展厅
  • 企业建设网站的空间有哪些宁波建设工程有限公司
  • 苏宁网站开发人员工资如何开通微信商城
  • 抚顺建设网站wordpress标签页面
  • 小精灵网站在线做语文中山做外贸网站
  • 深圳宝安沙井网站建设网站开发毕设参考文献
  • 成都建设厅官方网站查询怎么给购物网站做推广
  • 赤峰酒店网站建设哪家便宜seo关键词排名优化官网
  • 百度站长提交网址河北利用关键词优化网页