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

网站开发外包费用会计科目个人建网站

网站开发外包费用会计科目,个人建网站,拓者设计吧电脑版,外贸营销文案目录 一、线程池 1、线程池 2、线程池代码 3、线程池的应用场景 二、单例模式的线程安全问题 1、线程池的单例模式 2、线程安全问题 三、其他锁 一、线程池 1、线程池 线程池是一种线程使用模式。线程池里面可以维护一些线程。 为什么要有线程池#xff1f; 因为在…目录 一、线程池 1、线程池 2、线程池代码 3、线程池的应用场景 二、单例模式的线程安全问题 1、线程池的单例模式 2、线程安全问题 三、其他锁 一、线程池 1、线程池 线程池是一种线程使用模式。线程池里面可以维护一些线程。 为什么要有线程池 因为在我们使用线程去处理各种任务的时候尤其是一些执行时间短的任务我们必须要先对线程进行创建然后再进行任务处理最后再销毁线程效率是比较低的。而且有的时候线程过多会带来调度开销进而影响缓存局部性和整体性能。 于是我们可以通过线程池预先创建出一批线程线程池维护着这些线程线程等待着监督管理者分配可并发执行的任务。这避免了在处理短时间任务时创建与销毁线程的代价。 线程池不仅能够保证内核的充分利用还能防止过分调度。 2、线程池代码 我们先对线程进行封装Thread.hpp #pragma once #include iostream #include string #include cstdio #include pthread.husing namespace std; typedef void *(*fun_t)(void *);class ThreadData { public:void *arg_;string name_; };class Thread { public:Thread(int num, fun_t callback, void *arg): func_(callback){char buffer[64];snprintf(buffer, sizeof(buffer), Thread-%d, num);name_ buffer;tdata_.name_ name_;tdata_.arg_ arg;}void start(){pthread_create(tid_, nullptr, func_, (void *)tdata_);}void join(){pthread_join(tid_, nullptr);}string name(){return name_;}~Thread(){}private:pthread_t tid_;string name_;fun_t func_;ThreadData tdata_; }; 线程池代码threadPool.hpp #pragma once #include vector #include queue #include thread.hpp#define THREAD_NUM 3template class T class ThreadPool { public:bool Empty(){return task_queue_.empty();}pthread_mutex_t *getmutex(){return lock;}void wait(){pthread_cond_wait(cond, lock);}T gettask(){T t task_queue_.front();task_queue_.pop();return t;}public:ThreadPool(int num THREAD_NUM) : num_(num){for (int i 0; i num_; i){threads_.push_back(new Thread(i, routine, this));}pthread_mutex_init(lock, nullptr);pthread_cond_init(cond, nullptr);}static void *routine(void *arg){ThreadData *td (ThreadData *)arg;ThreadPoolT *tp (ThreadPoolT *)td-arg_;while (true){T task;{pthread_mutex_lock(tp-getmutex());while (tp-Empty())tp-wait();task tp-gettask();pthread_mutex_unlock(tp-getmutex());}cout xy task() pthread_self() endl;}}void run(){for (auto iter : threads_){iter-start();}}void PushTask(const T task){pthread_mutex_lock(lock);task_queue_.push(task);pthread_mutex_unlock(lock);pthread_cond_signal(cond);}~ThreadPool(){for (auto iter : threads_){iter-join();delete iter;}pthread_mutex_destroy(lock);pthread_cond_destroy(cond);}private:vectorThread * threads_;int num_;queueT task_queue_;pthread_mutex_t lock;pthread_cond_t cond; }; 任务task.hpp #pragma once#include iostream #include queue #include pthread.h #include unistd.hclass task { public:task(){}task(int x, int y): x_(x), y_(y){}int operator()(){return x_ y_;}private:int x_;int y_; }; 测试代码test.cc #include threadPool.hpp #include task.hpp #include iostream #include ctimeint main() {srand((unsigned int)time(nullptr) ^ getpid() ^ 12232);ThreadPooltask *tp new ThreadPooltask();tp-run();while (true){int x rand() % 100 1;sleep(1);int y rand() % 100 1;task t(x, y);tp-PushTask(t);cout x y ? endl;}return 0; } 运行结果  3、线程池的应用场景 1、需要大量的线程来完成任务且完成任务的时间比较短。  2、对性能要求苛刻的应用比如要求服务器迅速响应客户请求。 3、接受突发性的大量请求但不至于使服务器因此产生大量线程的应用。突发性大量客户请求在没有线程池情况下将产生大量线程虽然理论上大部分操作系统线程数目最大值不是问题短时间内产生大量线程可能使内存到达极限出现错误。 二、单例模式的线程安全问题 1、线程池的单例模式 首先我们要做的第一件事就是把构造函数私有再把拷贝构造和赋值运算符重载函数delete private:ThreadPool(int num THREAD_NUM) : num_(num){for (int i 0; i num_; i){threads_.push_back(new Thread(i, routine, this));}pthread_mutex_init(lock, nullptr);pthread_cond_init(cond, nullptr);}ThreadPool(const TreadPool other) delete;ThreadPool operator(const TreadPool other) delete; 接下来就要在类中定义一个成员变量静态指针方便获取单例对象并在类外初始化 //线程池中的成员变量 private:vectorThread * threads_;int num_;queueT task_queue_;pthread_mutex_t lock;pthread_cond_t cond;static ThreadPoolT *tp;//在类外初始化 ​template class T ThreadPoolT *ThreadPoolT::tp nullptr; 最后我们写一个函数可以获取单例对象在设置获取单例对象的函数的时候注意要设置成静态成员函数因为在获取对象前根本没有对象无法调用非静态成员函数无this指针:  static ThreadPoolT *getThreadPool() {if (tp nullptr){tp new ThreadPoolT();}return tp; } 2、线程安全问题 上面的线程池的单例模式看起来没有什么问题。可是当我们有多个线程去调用 getThreadPool函数去创建线程池的时候可能会有多个线程同时进入判断判断出线程池指针为空然后创建线程池对象。这样就会创建出多个线程池对象这就不符合我们单例模式的要求了所以我们必须让在同一时刻只有一个线程能够进入判断我们就要用到锁了。 定义一个静态锁并初始化 private:vectorThread * threads_;int num_;queueT task_queue_;pthread_mutex_t lock;pthread_cond_t cond;static ThreadPoolT *tp;static pthread_mutex_t lock;// 类外初始化 ​template class T pthread_mutex_t ThreadPoolT::lock PTHREAD_MUTEX_INITIALIZER; 对 getThreadPool函数进行加锁 static ThreadPoolT *getThreadPool(){if (tp nullptr){pthread_mutex_lock(lock);if (tp nullptr){tp new ThreadPoolT();}pthread_mutex_unlock(lock);}return tp;} 对于上面的代码我们为什么要在获取锁之前还要再加一个判断指针为空的条件呢 当已经有一个线程创建出来了线程池的单例模式后在这之后的所有其他线程即使申请到锁紧着着下一步就是去释放锁它不会进入第二个 if 条件里面。其实这样是效率低下的因为线程会频繁申请锁然后就释放锁。所以我们在最外层再加一个if判断就可以阻止后来的线程不用去申请锁创建线程池了直接返回已经创建出来的线程池。 三、其他锁 1、悲观锁在每次取数据时总是担心数据会被其他线程修改所以会在取数据前先加锁读锁写锁行锁等当其他线程想要访问数据时被阻塞挂起。 2、乐观锁每次取数据时候总是乐观的认为数据不会被其他线程修改因此不上锁。但是在更新数据前会判断其他数据在更新前有没有对数据进行修改。主要采用两种方式版本号机制和CAS操作。 ~ CAS操作当需要更新数据时判断当前内存值和之前取得的值是否相等。如果相等则用新值更新。若不等则失败失败则重试一般是一个自旋的过程即不断重试。 3、自旋锁说到自旋锁我们不得不说一说我们之前所用到的锁我们之前所用的锁都是互斥锁当线程没有竞争到互斥锁时它会阻塞等待只有等锁被释放了后才能去重新申请锁。而对于自旋锁当线程没有竞争到自旋锁的时候线程会不断地循环检测去申请自旋锁直到拿到锁。 一般来说如果临界区的代码执行时间比较长的话我们是使用互斥锁而不是自旋锁的这样线程不会因为频繁地检测去申请锁而占用CPU资源。如果临界区的代码执行时间较短的话我们一般就最好使用自旋锁而不是互斥锁因为互斥锁申请失败是要阻塞等待是需要发生上下文切换的如果临界区执行的时间比较短那可能上下文切换的时间会比临界区代码执行的时间还要长。
http://www.sczhlp.com/news/162243/

相关文章:

  • 西部虚拟主机网站后台不能访问企业网站备案号密码忘记
  • 中国建设银行网站缴费系统做企业竞争模拟的网站
  • 英文网站建设网站手机版网站设计
  • wordpress的站点地址和wordpress 文章模板
  • 5个在线设计网站郑州网站优化排名
  • 在哪个网站可做网络夫妻wp企业网站模板
  • 网站开发实践意义领地免费网站
  • wordpress 最新 调用wordpress优化攻略
  • 商河网站建设织梦后台如何做网站地图
  • 建设向58同城的网站wordpress链接默认是什么样子
  • 网络推广网站的方法手机app一般用什么开发
  • 网站流量统计主要指标包括做wordpress
  • 陈家镇建设发展公司网站企业网站欣赏
  • 做推广网站有什么一个备案号可以放几个网站
  • 普通网站建设费用站长工具seo查询
  • hdsyscms企业建站系统python能开发app吗
  • 深圳个性化建网站公司广州网站建设 推广公司哪家好
  • 安徽省建设厅网站职称网络平台怎么创建需要多少钱
  • 制作app免费网站模板下载建一个优化网站多少钱
  • 自己制作的网站建设网站花都
  • 黄骅港信息吧百度贴吧谷歌优化seo
  • 制作免费制作个人网站怎么做网站开发 q3687474
  • 带m开头的网站怎么做广东深圳职业技术学院
  • 二级网站建设要求软件工程师考试报名
  • 做团购的家居网站有哪些wordpress access数据库
  • 做设计一般用的素材网站是什么上海中风险地区清零
  • 药业集团网站策划方案范文asp.net 网站数据库
  • 新乡营销型网站建设wordpress表格样式插件
  • 网站链接分析手机端设计
  • 帝国cms7.0网站地图网页设计素材收集