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

龙岗-网站建设深圳信科信息流广告是什么

龙岗-网站建设深圳信科,信息流广告是什么,在记算机上登陆一个网站点怎么做,公司网站建设哪个好关于多线程的概念与理解,可以先了解Linux下的底层线程。当对底层线程有了一定程度理解以后,再学习语言级别的多线程编程就轻而易举了。 【Linux】多线程 -> 从线程概念到线程控制 【Linux】多线程 -> 线程互斥与死锁 语言级别的…

关于多线程的概念与理解,可以先了解Linux下的底层线程。当对底层线程有了一定程度理解以后,再学习语言级别的多线程编程就轻而易举了。

【Linux】多线程 -> 从线程概念到线程控制

【Linux】多线程 -> 线程互斥与死锁


语言级别的多线程编程最大的好处就是可以跨平台,使用语言级别编写的多线程程序不仅可以在Windows下直接编译运行,在Linux下也是可以直接编译运行的。其实本质还是调用了不同操作系统的底层线程API。

多线程简单使用

  • 怎么创建启动一个线程?

#include<iostream>
#include<thread>
#include<chrono>void threadHandle1(int time)
{// 让线程休眠两秒std::this_thread::sleep_for(std::chrono::seconds(time));std::cout << "hello thread1" << std::endl;
}int main()
{// 创建一个线程对象,传入线程函数以及线程函数所需要的参数,线程就开始执行了std::thread t1(threadHandle1, 2);// 主线程等待子线程结束,再继续往下运行t1.join();std::cout << "main thread done!" << std::endl;return 0;
}

主线程要t1.join()等待子线程结束之后才能向后运行。如果不等待,就会异常终止。

  • 子线程如何结束?

子线程函数运行完成就结束了。

也可以将线程设置为分离状态,主线程就可以不用等待子进程执行完再继续向后运行了。

void threadHandle1(int time)
{// 让线程休眠两秒std::this_thread::sleep_for(std::chrono::seconds(time));std::cout << "hello thread1" << std::endl;
}int main()
{// 创建一个线程对象,传入线程函数以及线程函数所需要的参数,线程就开始执行了std::thread t1(threadHandle1, 2);// 主线程等待子线程结束,再继续往下运行// t1.join();// 设置线程为分离状态t1.detach();std::cout << "main thread done!" << std::endl;return 0;
}

  •  主线程如何处理子线程?

1、t1.join()等待线程,等待线程结束后主线程再继续向后运行。

2、t1.detach()分离线程,主线程结束,整个进程就结束了,所有线程都自动结束了。


#include<iostream>
#include<thread>
#include<chrono>void threadHandle1(int time)
{// 让线程休眠time秒std::this_thread::sleep_for(std::chrono::seconds(time));std::cout << "hello thread1" << std::endl;
}void threadHandle2(int time)
{// 让线程休眠time秒std::this_thread::sleep_for(std::chrono::seconds(time));std::cout << "hello thread1" << std::endl;
}int main()
{// 创建一个线程对象,传入线程函数以及线程函数所需要的参数,线程就开始执行了std::thread t1(threadHandle1, 2);std::thread t2(threadHandle2, 2);// 主线程等待子线程结束,再继续往下运行t1.join();t2.join();// 设置线程为分离状态// t1.detach();std::cout << "main thread done!" << std::endl;return 0;
}

 mutex互斥锁和lock_guard

#include<iostream>
#include<thread>
#include<list>int tickets = 1000;void getTicket(int i)
{// 模拟用户抢票的行为while (tickets > 0){std::cout << "用户:" << i << "正在进行抢票!" << tickets << std::endl;tickets--;std::this_thread::sleep_for(std::chrono::microseconds(100));}
}int main()
{std::list<std::thread> list;for (int i = 1; i <= 3; i++){list.push_back(std::thread(getTicket, i));}for (std::thread &t: list){t.join();}return 0;
}

输出的结果杂乱无章,并且抢票出现负数。

多线程对临界区的访问会存在竞态条件:临界区代码段在多线程环境下执行,随着线程的调度时许不同,从而产生不同的结果。所以,我们要保证对临界区的原子操作,是通过对临界区加锁完成的。

由于多个线程同时向标准输出流std::cout输出信息,会造成输出混乱,各线程的输出可能相互穿插。

在多线程环境下,多个线程同时访问和修改共享资源tickets,会引发数据竞争问题。比如,当一个线程检查到tickets>0后,在执行tickets--操作之前,另一个线程也可能检查到tickets>0,进而导致重复售票或者出现负数票数的情况。

++/--操作并不是原子性的,其实是对应三条汇编指令完成的。

  • 读取:从内存中把变量的值读取到寄存器
  • 修改:在寄存器里将变量的值+1/-1
  • 写入:把修改后的值写入到内存

在单线程环境下,这三个步骤顺序执行不会有问题。但是在多线程环境下,多个线程可能对同一个变量同时进行++/--操作,从而导致数据竞争的问题。

可以看下面的过程演示。

一:

二:

三:

C++11是通过加锁来保证++/--操作的原子性的。


#include<iostream>
#include<thread>
#include<list>
#include<mutex>int tickets = 1000;
std::mutex mtx; // 全局的一把锁void getTicket(int i)
{// 模拟用户抢票的行为while (tickets > 0){mtx.lock();// 锁+双重判断,如果不双重判断,当tickets为1时,用户正在抢票还没有执行到tickets--,其他用户判断tickets>0,也进来了等待锁。// 用户抢票之后,其他用户获取到锁还会进行抢票。if (tickets > 0){// 临界区代码段 - 加锁保护std::cout << "用户:" << i << "正在进行抢票!" << tickets << std::endl;tickets--;mtx.unlock();}}
}int main()
{std::list<std::thread> list;for (int i = 1; i <= 3; i++){list.push_back(std::thread(getTicket, i));}for (std::thread &t: list){t.join();}return 0;
}

通过加锁和双重判断的方式,这样就能做到对多线程对共享资源tickets的安全访问了。

lock_guard和unique_lock

其实不需要我们手动加锁和解锁,因为,如果临界区内有return,break等语句,此线程获取锁,但是在释放锁之前break或者renturn了,导致锁没有释放。那么其他线程也获取不了锁,就会造成死锁问题,所以对于这把互斥锁要有RAII的思想。

使用lock_guard。构造函数获取锁,析构函数释放锁。

int tickets = 1000;
std::mutex mtx; // 全局的一把锁void getTicket(int i)
{// 模拟用户抢票的行为while (tickets > 0){{std::lock_guard<std::mutex> lock(mtx);// mtx.lock();// 锁+双重判断,如果不双重判断,当tickets为1时,用户正在抢票还没有执行到tickets--,其他用户判断tickets>0,也进来了等待锁。// 用户抢票之后,其他用户获取到锁还会进行抢票。if (tickets > 0){std::cout << "用户:" << i << "正在进行抢票!" << tickets << std::endl;tickets--;}// mtx.unlock();}std::this_thread::sleep_for(std::chrono::microseconds(100));}
}

不管临界区是正常执行,还是break或return了,出了作用域,lock_guard会自动调用析构函数释放锁,保证所有线程都能释放锁,避免死锁问题发生。

lock_guard不支持拷贝构造和赋值运算符重载,如果需要拷贝和赋值可以使用unique_lock,支持移动语义,可以使用右值引用的拷贝构造和赋值运算符重载。

int tickets = 1000;
std::mutex mtx; // 全局的一把锁void getTicket(int i)
{// 模拟用户抢票的行为while (tickets > 0){{std::unique_lock<std::mutex> lck(mtx);// std::lock_guard<std::mutex> lock(mtx);// mtx.lock();// 锁+双重判断,如果不双重判断,当tickets为1时,用户正在抢票还没有执行到tickets--,其他用户判断tickets>0,也进来了等待锁。// 用户抢票之后,其他用户获取到锁还会进行抢票。if (tickets > 0){std::cout << "用户:" << i << "正在进行抢票!" << tickets << std::endl;tickets--;}// mtx.unlock();}std::this_thread::sleep_for(std::chrono::microseconds(100));}
}

总结:lock_guard不能用在函数传递或返回的过程中,因为lock_guard删除了拷贝构造和赋值,只能用在简单的临界区代码段的互斥操作中。unique_guard可以用在函数传递或返回的过程中,因为支持移动语义,可以使用移动构造和移动赋值。unique_guard通常与条件变量一起使用。

线程间的同步通信

生产者-消费者模型

std::mutex mtx;
std::condition_variable cv;// 边生产边消费
class Queue
{
public:void put(int val){// 加锁std::unique_lock<std::mutex> lock(mtx);// 如果队列不为空,则等待while (!que.empty()){// 1.进入等待状态 2.释放锁cv.wait(lock);// 被唤醒之后,等待状态进入阻塞状态,获取锁进入就绪状态继续执行}que.push(val);cv.notify_all(); // 通知消费者消费std::cout << "生产者 生产:" << val << "号物品" << std::endl;}int get(){// 加锁std::unique_lock<std::mutex> lock(mtx);// 如果队列为空,则等待while (que.empty()){// 1.进入等待状态 2.释放锁cv.wait(lock);// 被唤醒之后,等待状态进入阻塞状态,获取锁进入就绪状态继续执行}int val = que.front();que.pop();cv.notify_all(); // 通知生产者生产std::cout << "消费者 消费:" << val << "号物品" << std::endl;return val;}
private:std::queue<int> que;
};// 生产
void producer(Queue* que)
{for (int i = 0; i <= 10; i++){que->put(i);std::this_thread::sleep_for(std::chrono::microseconds(100));}
}
// 消费
void conducer(Queue* que)
{for (int i = 0; i <= 10; i++){que->get();std::this_thread::sleep_for(std::chrono::microseconds(100));}
}
int main()
{Queue que;std::thread p(producer, &que);std::thread c(conducer, &que);p.join();c.join();return 0;
}

http://www.dtcms.com/wzjs/183264.html

相关文章:

  • 深圳福田大型商城网站建设电子商务网站建设流程
  • 个人备案公司网站个人免费开发app
  • 网站代码上传后无法打开石家庄百度推广优化排名
  • 做网站怎么上词一级造价工程师
  • asp.net网站开发模板开发网站建设
  • asp开源政府网站网站查询ip
  • 淘宝网站详情页怎么做武汉seo群
  • web做网站实验报告做网站推广
  • 医院网站管理办法策划方案网站
  • 项目外包公司到底值不值得去seo的课谁讲的好
  • 网站中链接怎么做安卓优化大师hd
  • 广州小程序开发方案seo智能优化
  • 做网站1008做网站 - 百度2345网址大全设主页
  • wordpress如何自动采集网站图片电商平台排行榜前十名
  • 长沙营销型网站制作费用武汉seo招聘
  • 南京做电商网站的公司简介网络建站流程
  • 北京网站建设价格便宜兰州网络推广关键词优化
  • 免费男人做那个的视频网站seo主管招聘
  • 山西建设局网站首页搜索引擎优化的要点
  • 快速制作效果图软件如何做网站推广及优化
  • 校园网站平台建设公众号seo排名优化
  • 县级政府网站建设费用怎么建网站详细步骤
  • 怎么制作网站上传视频搜狐视频
  • 网站建设来发票软文推广文章范文1000
  • 网站上百度要怎么做鼓楼网站seo搜索引擎优化
  • 哪些做直播卖食品的网站手机怎么创建自己的网站平台
  • 营销型网站建设网站建设营销说到很多seo人员都转行了
  • 响应式全屏网站深圳网站关键词
  • 西安知名网站推广宁波网络推广产品服务
  • 卡盟怎么网站怎么做武汉谷歌seo