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

深圳市有方科技有限公司搜索引擎优化的基本内容

深圳市有方科技有限公司,搜索引擎优化的基本内容,做直播的在相亲网站交友,做推广什么网站好目录 第一节:thread的主要内容 1-1.创建子线程 1-2.回收子线程 1-3.获得子线程的id 1-4.获得当前线程id 1-5.子线程传引用 1-6.线程的先创建后使用 第二节:mutex的主要内容 2-1.mutex的作用 2-2.智能锁 第三节:condition_variable的主要内…

目录

第一节:thread的主要内容

        1-1.创建子线程

        1-2.回收子线程

        1-3.获得子线程的id

        1-4.获得当前线程id

        1-5.子线程传引用

        1-6.线程的先创建后使用

第二节:mutex的主要内容

        2-1.mutex的作用

        2-2.智能锁

第三节:condition_variable的主要内容

        3-1.休眠线程

         3-2.唤醒线程

下期预告:


第一节:thread的主要内容

        C++11引入了<thread>库来管理线程,它将线程包装成一种类来管理。

        1-1.创建子线程

std::thread t1(可调用对象,可变参数);

        t1:这个线程的管理句柄,主线程通过它管理这个子线程。

        可调用对象:这个线程创建时就会执行的函数,又叫任务

        可变参数:如果任务有参数,就在这里传入。

        1-2.回收子线程

        

t1.join();

        这行代码一般由主线程调用,而且它是阻塞的,即主线程等待子线程 t1 的任务完成之后再退出,如果不等待而主线程先退出,主线程的数据被回收。由于同一进程的线程之间的很多数据都是共享的,就会影响子线程的功能。

        

        1-3.获得子线程的id

t1.get_id();

         系统给每个线程都赋予了一个唯一的id,用来管理所有的线程,主线程可以使用上述代码获取某个子线程的id。

        1-4.获得当前线程id

this_thread::get_id();

        线程可以使用上述代码获取自己的id,主线程也可以获取自己的id。 

        1-5.子线程传引用

        子线程执行的任务函数也可以传引用,除了形参的位置用引用接受外,传参数时必须用ref()括起来:

void task(int& a)
{//...
}
int main()
{int a = 1;std::thread t1(task,ref(a));// 等待线程退出t1.join();return 0;
}

        1-6.线程的先创建后使用

        线程在被创建时,如果不传入任何任务函数时是被阻塞的:

	std::vector<std::thread> thrpool(10); // 创建10个线程,但不执行函数

        线程不支持拷贝构造,但是支持移动构造和移动赋值,那么就可以使用具有右值属性的std::thread类进行赋值,让thrpool中的线程运行起来:

void task()
{std::cout << "线程执行任务" << ",id:"<<std::this_thread::get_id() << std::endl;
}
int main()
{std::vector<std::thread> thrpool; // 创建10个线程,但不执行函数thrpool.resize(10);// 移动赋值for (auto& thread : thrpool){thread = std::thread(&task);Sleep(2);}// 等待所有线程结束for (auto& thread : thrpool){thread.join();}return 0;
}

   

第二节:mutex的主要内容

        2-1.mutex的作用

        mutex意为锁,它用来锁住某些共享资源,防止引发线程安全的问题,请看以下的例子:

#include <thread>
#include <windows.h>int tickets = 1000; // 票数void buyTicket()
{while (true){if (tickets > 0){tickets--;std::cout << "线程: " << std::this_thread::get_id()<< " 购买了一张票, 剩余票数: " << tickets << std::endl;}else{break; // 如果没有票了,退出循环}}
}int main()
{std::thread t1(buyTicket);std::thread t2(buyTicket);std::thread t3(buyTicket);// 等待线程退出t1.join();t2.join();t3.join();return 0;
}

         我让3个线程抢票,当票为0时退出,按理来说每个线程抢到票后,剩余的票数应该是不同的,但是上述代码不够完善,可能会出现剩余票数为负数的情况。

         因为CPU是以时间片轮转的形式运行线程,如果线程1进入 if 后,此时tickets为1,线程1还未执行 tickets-- 就被剥离CPU了,线程2判断 if 时,因为tickets还是1,线程2也会执行一次 tickets-- 。        

        然后线程1回来之后也会执行一次 tickets-- 。这就导致为1的tickets被执行了两次--,它的值就变成-1了。

        为了避免这种情况,需要保证进入 if 的线程同时只有一个,这就需要用到mutex。

        mutex是一种资源,同时只有一个线程能拥有它,其他线程就会在mutex的位置进行阻塞等待,直到拥有它的线程把mutex释放掉:

std::mutex mtx; // 初始化一个锁
void buyTicket()
{while (true){mtx.lock(); // 上锁:线程获取锁// 检查和修改 tickets 没有同步if (tickets > 0){--tickets;std::cout << "线程: " << std::this_thread::get_id()<< " 购买了一张票, 剩余票数: " << tickets << std::endl;}else{mtx.unlock(); // 解锁:线程释放锁break; // 如果没有票了,退出循环}mtx.unlock(); // 解锁:线程释放锁}
}

  

        这样就正常了。

        mutex的意思就是锁,它就像锁一样,锁住其他线程,不让它们继续执行代码,直到拥有锁的线程解锁。 

        2-2.智能锁

        就像new空间的指针一样,如果出作用域后没有释放锁,那么其他线程就会一直等待锁,线程就不能正常退出了,所以C++引入了智能锁。

        智能锁需要一个锁进行构造,构造成功后会自动上锁,出作用域它会析构,自动解锁

std::mutex mtx;
void buyTicket()
{while (true){std::unique_lock<std::mutex> lock(mtx); // 智能锁if (tickets > 0){--tickets;std::cout << "线程: " << std::this_thread::get_id()<< " 购买了一张票, 剩余票数: " << tickets << std::endl;}else{// 出作用域自动解锁break;}lock.unlock(); // 未出作用域,手动解锁}
}

 

第三节:condition_variable的主要内容

        condition_variable提供了条件变量相关接口,它需要配合锁使用。

        3-1.休眠线程

std::mutex mtx;
std::condition_variable con;std::unique_lock<std::mutex> lock(mtx)
con.wait(lock);

        线程执行 con.wait(mtx) 时就会一直被休眠阻塞。

        条件变量阻塞线程的原理是让持有对应锁的线程释放锁,并使之休眠,等待唤醒。

        注意条件变量只允许传入智能锁(unique_lock),而不允许直接传入锁(mutex)。

         3-2.唤醒线程

con.notify_one(); // 随机唤醒一个线程
con.notify_all(); // 唤醒所有线程

        唤醒一个线程时,该线程直接就可以获得条件变量中的锁来执行后面的代码了,其他线程继续休眠。

        唤醒所有线程后,这些线程仍然需要先竞争条件变量中的锁,竞争到锁的一个线程才能执行后面的代码,其他线程没有继续休眠,而是阻塞等待锁被释放,然后竞争锁。

        wait的第二个参数还可以传入一个可调用对象,线程被唤醒时,还需要可调用对象的返回值为真时才能获得锁。

        不传入默认为真。

std::mutex mtx;
std::condition_variable con;
bool ready = false;
void worker(int id)
{std::unique_lock<std::mutex> lock(mtx);con.wait(lock, [] {return ready; });// 唤醒后仍需持有锁才能执行下面的代码std::cout << "线程 " << id << " 被唤醒并执行。" << std::endl;
}int main()
{std::thread t1(worker, 1);std::thread t2(worker, 2);std::thread t3(worker, 3);// 确保所有线程都进入等待状态std::this_thread::sleep_for(std::chrono::milliseconds(100));// 唤醒所有线程std::cout << "唤醒所有线程" << std::endl;ready = true; // 设置为真con.notify_all();t1.join();t2.join();t3.join();return 0;
}

  

 

下期预告:

        第十九章将讲述C++11引入的另一种概念——异常。

        它可以帮助程序员更快的定位错误。

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

相关文章:

  • 布吉附近公司做网站建设多少钱收录优美图片
  • 公司部门名称及部门职能长沙seo搜索
  • 网站备案时网站没有内容可以免费seo诊断
  • 漳州做网站建设公司短视频推广平台有哪些
  • html个人简历代码沈阳沈河seo网站排名优化
  • 公司做网站哪家好建网站公司哪里好
  • 电力建设期刊网站爱站网查询
  • 头像设计易做图网站网站建设平台软件
  • 银行网站维护是做哪些app推广拉新一手渠道代理
  • 电子工程师在哪里报名成都搜索优化整站优化
  • 乐成高端网站建设怎么引流推广自己的产品
  • 企业网站管理系统 软件著作权长沙seo工作室
  • 海南高端网站建设seo从0到1怎么做
  • 中国住房和城乡建设部网站2022年新闻摘抄十条简短
  • 河间申梦网站建设制作雅虎日本新闻
  • 网站建设 配资百度招聘电话
  • 环境设计专业资料网站友情链接网站源码
  • 无锡建设网站的公司上海最新疫情
  • 网站开发合同注意广州百度推广客服电话多少
  • 如何高效率的建设网站十大销售管理软件排行榜
  • wordpress 前端展示池州网站seo
  • 如何在本地发布自己做的网站社区营销
  • 怎样做网站怎要加服务器软文代写平台有哪些
  • 网站建设需要掌握什么技术百度搜索热度
  • 专题网站建设方案目前疫情最新情况
  • 做商贸网站搜索电影免费观看播放
  • 深圳提供网站建设制作seo标题优化分析范文
  • 专门设计网站的公司叫什么seo怎么优化关键词排名
  • 网站备案的坏处信息流优化师前景
  • 北沙滩网站建设公司网络营销专业介绍