C++11 多线程 基础
C++11开始支持多线程编程,之前多线程编程都需要系统的支持,在不同的系统下创建线程需要不同的API如pthread_create(),Createthread(),beginthread()等,使用起来都比较复杂,C++11提供了新头文件<thread>、<mutex>、<atomic>、<future>等用于支持多线程。
使用C++11开启一个线程是比较简单的,下面来看一个简单的例子:
#include <thread>
#include <iostream>
void hello()
{
std::cout << "Hello from thread " << std::endl;
}
int main()
{
std::thread t1(hello);
t1.join();
std::cout<<"Main Thread"<<std::endl;
return 0;
}
运行结果:
说明,通过thread 类直接申明一个线程t1,参数是这个线程执行的回调函数的地址,通过jion()方法阻塞主线程,直到t1线程执行结束为止。
C++11支持Lambda表达式,因此一个新线程的回调函数也可以是有一个Lambda表达式的形式,但是注意如果使用Lambda表达式最好不要使用引用的方式,应该使用值传递的方式来访问数据,在多线程中使用引用容易造成混乱。下面这个例子稍微复杂,创建了多个子线程,并使用了get_id()方法来获取当前线程的id。
#include <thread>
#include <iostream>
#include <vector>
int main()
{
std::vector<std::thread> threads;
for(int i = 0; i < 5; ++i){
threads.push_back(std::thread([](){
std::cout << "Hello from lamda thread " << std::this_thread::get_id() << std::endl;
}));
}
for(auto& thread : threads){
thread.join();
}
std::cout<<"Main Thread"<<"\t"<<std::this_thread::get_id()<<std::endl;
return 0;
}
运行结果:
上述代码中,使用vector来存放每个线程,线程的回调函数通过Lambda表达式产生,注意后面join的使用方式。
可以通过sleep_for来使线程睡眠一定的时间:
#include <thread>
#include <iostream>
#include <mutex>
using namespace std;
int main()
{
std::mutex m;
thread t1([&m]()
{
std::this_thread::sleep_for (chrono::seconds(10));
for(int i=0;i<10;i++)
{
m.lock();
cout << "In t1 ThreadID : " << std::this_thread::get_id() << ":" << i << endl;
m.unlock ();
}
} );
thread t2([&m]()
{
std::this_thread::sleep_for (chrono::seconds(1));
for(int i=0;i<10;i++)
{
m.lock ();
cout << "In t2 ThreadID : " << std::this_thread::get_id() << ":" << i << endl;
m.unlock();
}
} );
t1.join();
t2.join();
cout<<"Main Thread"<<endl;
return 0;
}
运行结果:
可以看出,由于线程t1睡眠的时间较长,t2先执行了。
延时有这几种类型:nanoseconds、microseconds、milliseconds、seconds、minutes、hours。
在使用多线程的程序中操作共享数据的时候一定要小心,由于线程的乱序执行,可能会得到意想不到的结果。通过下面的程序来看:
#include <thread>
#include <iostream>
#include <vector>
#include <mutex>
struct Counter {
std::mutex mutex;
int value;
Counter() : value(0) {}
void increment(){
// mutex.lock(); 【1】表示没有使用锁
++value;
// mutex.unlock(); 【1】
}
void decrement(){
mutex.lock();
--value;
mutex.unlock();
}
};
int main(){
Counter counter;
std::vector<std::thread> threads;
for(int i = 0; i < 5; ++i){
threads.push_back(std::thread([&](){
for(int i = 0; i < 10000; ++i){
counter.increment();
}
}));
}
for(auto& thread : threads){
thread.join();
}
std::cout << counter.value << std::endl;
return 0;
}
运行结果:
【1】
运行结果:(使用了锁)
说明:由于创建线程是使用lambda表达式,并使用引用的方式访问counter这个变量,当没有使用lock来保护的时候(情况【1】),执行的结果可能不像预期的5000(程序的意思是每个线程使counter中的value自加1000次,5个线程运行结束的时候应该是5000),当没有使用锁的时候自加的操作可能被其他线程打断,因此结果可能会小于5000。
C++11 多线程 基础的更多相关文章
- Java多线程干货系列—(一)Java多线程基础
前言 多线程并发编程是Java编程中重要的一块内容,也是面试重点覆盖区域,所以学好多线程并发编程对我们来说极其重要,下面跟我一起开启本次的学习之旅吧. 正文 线程与进程 1 线程:进程中负责程序执行的 ...
- Java多线程干货系列(1):Java多线程基础
原文出处: 嘟嘟MD 前言 多线程并发编程是Java编程中重要的一块内容,也是面试重点覆盖区域,所以学好多线程并发编程对我们来说极其重要,下面跟我一起开启本次的学习之旅吧. 正文 线程与进程 1 线程 ...
- [转]Java多线程干货系列—(一)Java多线程基础
Java多线程干货系列—(一)Java多线程基础 字数7618 阅读1875 评论21 喜欢86 前言 多线程并发编程是Java编程中重要的一块内容,也是面试重点覆盖区域,所以学好多线程并发编程对我们 ...
- C++11 并发指南九(综合运用: C++11 多线程下生产者消费者模型详解)
前面八章介绍了 C++11 并发编程的基础(抱歉哈,第五章-第八章还在草稿中),本文将综合运用 C++11 中的新的基础设施(主要是多线程.锁.条件变量)来阐述一个经典问题——生产者消费者模型,并给出 ...
- c++11 多线程入门教程(一)
原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/10945309.html 最近在找c++服务端开发的实习(大佬们有推荐吗QAQ..),恰好写了一 ...
- c++11 多线程 -- 基本使用
c++11 多线程 – 基本使用 前言:这篇文章仅针对没有使用过c++11线程库的童鞋来高速入门,也是自己的一个简单记录,内容比較基础. 1.线程的基本使用 2.相互排斥量 3.条件变量 4.原子变量 ...
- Java 多线程基础(十一)线程优先级和守护线程
Java 多线程基础(十一)线程优先级和守护线程 一.线程优先级 Java 提供了一个线程调度器来监控程序启动后进去就绪状态的所有线程.线程调度器通过线程的优先级来决定调度哪些线程执行.一般来说,Ja ...
- C++多线程基础教程
目录 1 什么是C++多线程? 2 C++多线程基础知识 2.1 创建线程 2.2 互斥量使用 lock()与unlock(): lock_guard(): unique_lock: conditio ...
- Java基础知识笔记(四:多线程基础及生命周期)
一.多线程基础 编写线程程序主要是构造线程类.构造线程类的方式主要有两种,一种是通过构造类java.lang.Thread的子类,另一种是通过构造方法实现接口java.lang.Runnable的类. ...
随机推荐
- 解决svn状态图标不显示的办法
SVN是一款出色的代码版本控制工具,大部分开发者都在使用.由于前不久刚做了系统,所以要重装一下SVN,结果就出了问题,问题就是,不管是文件处于什么状态他的提示图标都不显示,这就太不给力了吧.通过搜寻, ...
- Java基础知识强化34:String类之String类的转换功能
1. String类的转换功能 String[] split(String regex)//将字符串变成字符串数组(字符串切割) byte[] getBytes()//将字符串变成字节数组 char[ ...
- LSI SAS 2308配置操作
介绍LSISAS2308的配置操作 3.1 登录CU界面 介绍登录LSISAS2308的CU配置界面的方法. 3.2 创建RAID 介绍在LSISAS2308扣卡上创建RAID的操作方法. 3.3 配 ...
- 部署hibernate框架项目时出现问题:The type java.lang.Object cannot be resolved. It is indirectly referenced from required .class files.
基本情况: (这些其实关系不大)我是直接impor导入HibernateDemo项目到eclipse中的,该项目的hibernate版本是3.6.7.Final版,使用了Hibernate Tools ...
- JS简单实现图片切换
<!DOCTYPE html><html> <head> <meta charset="utf-8" /> <title> ...
- 浅述Oracle分布式事务概念
着系统的复杂性不断增加,我们所面对的分布式系统渐渐增加.分布式文件系统.分布式消息队列系统等等层出不穷,在一些行业特别是互联网行业应用广泛.分布式数据库也是目前使用比较常用的分布式系统之一. 简单来说 ...
- c3p0写连接池 Demo
1.导包 2.配置文件:名称必须为:c3p0-config.xml,且必须放在src根目录下 <c3p0-config> <!-- 默认配置,有且仅可出现一次 ,如果没有指定则使用这 ...
- tomcat启动报错总结
错误一 webapps\ROOT does not exist or is not a readable directory 错误原因:在tomcat的server.xml的context中配置了不存 ...
- Guava API学习之Ordering犀利的比较器 编辑
Ordering是Guava类库提供的一个犀利强大的比较器工具,Guava的Ordering和JDK Comparator相比功能更强.它非常容易扩展,可以轻松构造复杂的comparator,然后用在 ...
- 关于ajax直接提交表单jQuery .validator验证不起作用问题
之前用$.ajax(function(){});直接提交表单,而表单验证不通过也能提交. $(document).ready(function(){ $.ajax({ url:" ...