一、std::future的其他成员函数
//枚举类型:wait_for
// 线程8.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include<future>
#include<thread>
#include<iostream>
using namespace std;
#include<vector>
int mythread(int mypar)
{
cout << "mypar = " << mypar << endl;
cout << "mythread() start " << "threadid = " << std::this_thread::get_id() << endl;
std::chrono::milliseconds dura(5000);
std::this_thread::sleep_for(dura);
cout << "mythread() end " << "threadid = " << std::this_thread::get_id() << endl;
return 5;
}
int main()
{
cout << "main " << "threadid = " << std::this_thread::get_id() << endl;
std::future<int> result = std::async(std::launch::deferred,mythread,5); //创建一个线程开始执行,绑定关系,流程不卡在这
cout << "contine...." << endl;
int def = 0;
//cout << result.get() << endl; //卡在这里等待mythread()执行完毕,拿到返回值 自能调用一次
//result.wait();//等待线程返回,本身不返回结果
//一、std::future的其他成员函数
//枚举类型:wait_for
std::future_status status = result.wait_for(std::chrono::seconds(0));//等待一秒
if (status == std::future_status::timeout)
{
cout << "超时" << endl;
}
else if (status == std::future_status::ready)
{
cout << "线程成功执行完毕,返回" << endl;
cout << result.get() << endl;
}
else if (status == std::future_status::deferred)
{
cout << "线程被延迟执行" << endl;
cout << result.get() << endl;
}
return 0;
}
二、std::shared_future类模板
// 线程8.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include<future>
#include<thread>
#include<iostream>
using namespace std;
#include<vector>
int mythread(int mypar)
{
cout << "mypar = " << mypar << endl;
cout << "mythread() start " << "threadid = " << std::this_thread::get_id() << endl;
std::chrono::milliseconds dura(5000);
std::this_thread::sleep_for(dura);
cout << "mythread() end " << "threadid = " << std::this_thread::get_id() << endl;
return 5;
}
void mythread2(std::shared_future<int>&tmpf)
{
cout << "mythread2() start" << " threadid = " << std::this_thread::get_id() << endl;
auto result = tmpf.get();
cout << " mythread2 result = " << result << endl;
}
int main()
{
//二、std::shared_future类模板,get()函数是复制数据
cout << "main " << "threadid = " << std::this_thread::get_id() << endl;
std::packaged_task<int(int)>mypt(mythread);
std::thread t1(std::ref(mypt),1);
t1.join();
/*01
std::future<int> result = mypt.get_future();
bool ifcan = result.valid();
//std::shared_future<int> result_s(std::move(result));
std::shared_future<int> result_s(result.share());//执行完毕后result_s里面有值,result里面空
bool ifcan1 = result.valid();
auto mythreadresult = result_s.get();
mythreadresult = result_s.get(); //get多次
*/
//02
std::shared_future<int> result_s(mypt.get_future());//通过get_future返回值直接构造一个shared_future对象
auto mythreadresult = result_s.get();
mythreadresult = result_s.get(); //get多次
std::thread t2(mythread2,std::ref(result_s));
t2.join();
return 0;
}
三、原子操作std::atomic 类模板 封装某个值
互斥量:多线程编程中 保护共享数据;锁,操作共享数据
有两个线程,一个线程读变量值,一个线程写值
原子操作理解:不需要用到互斥量加锁(无锁),技术的多线程并发编程方式
原子操作:是在多线程中,不会被打断的 程序执行片段; 比互斥量更高效率
互斥量加锁一般为一个代码段,而原子操作一般都是一个变量
原子操作,一般指”不可分割的操作“,也就是说这种操作要么完成,要么没完成,不可能出现半完成状态。
正常加有问题
// 线程8.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include<future>
#include<thread>
#include<iostream>
using namespace std;
#include<vector>
//std::atomic<int> g_mycount = 0;//定义一个全局变量
//std::mutex g_my_mutex;
int g_mycount = 0;
void mythread() //线程入口函数
{
for (int i = 0;i<1000000;i++)
{
//g_my_mutex.lock();
g_mycount++; //加时会被打断
//g_my_mutex.unlock();
//g_mycount++;//对应的操作是原子操作,不会被打断
}
}
int main()
{
thread myobj1(mythread);
thread myobj2(mythread);
myobj1.join();
myobj2.join();
cout << "两个线程执行完毕 结果 = " << g_mycount << endl;
return 0;
}
两个线程执行完毕 结果 = 1207351
请按任意键继续. . .
不等于2000000
带互斥量效率低
// 线程8.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include<future>
#include<thread>
#include<iostream>
using namespace std;
#include<vector>
//std::atomic<int> g_mycount = 0;//定义一个全局变量
std::mutex g_my_mutex;
int g_mycount = 0;
void mythread() //线程入口函数
{
for (int i = 0;i<1000000;i++)
{
g_my_mutex.lock();
g_mycount++;
g_my_mutex.unlock();
//g_mycount++;//对应的操作是原子操作,不会被打断
}
}
int main()
{
thread myobj1(mythread);
thread myobj2(mythread);
myobj1.join();
myobj2.join();
cout << "两个线程执行完毕 结果 = " << g_mycount << endl;
return 0;
}
两个线程执行完毕 结果 = 2000000
请按任意键继续. . .
原子操作std::atomic
// 线程8.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include<future>
#include<thread>
#include<iostream>
using namespace std;
#include<vector>
std::atomic<int> g_mycount = 0;//定义一个全局变量
//std::mutex g_my_mutex;
//int g_mycount = 0;
void mythread() //线程入口函数
{
for (int i = 0;i<1000000;i++)
{
/*g_my_mutex.lock();
g_mycount++;
g_my_mutex.unlock();*/
g_mycount++;//对应的操作是原子操作,不会被打断
}
}
int main()
{
thread myobj1(mythread);
thread myobj2(mythread);
myobj1.join();
myobj2.join();
cout << "两个线程执行完毕 结果 = " << g_mycount << endl;
return 0;
}
两个线程执行完毕 结果 = 2000000
请按任意键继续. . .
// 线程8.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include<future>
#include<thread>
#include<iostream>
using namespace std;
#include<vector>
std::atomic<bool>g_ifend = false;
void mythread()
{
std::chrono::microseconds dura(1000);
while (g_ifend == false)
{
cout << "thread id = " << std::this_thread::get_id()<<"运行中" << endl;
std::this_thread::sleep_for(dura);
}
cout << "thread id = " << std::this_thread::get_id() << "运行结束" << endl;
}
int main()
{
thread myobj1(mythread);
thread myobj2(mythread);
std::chrono::microseconds dura(5000);
std::this_thread::sleep_for(dura);
g_ifend = true;
myobj1.join();
myobj2.join();
cout << "程序退出" << endl;
return 0;
}
原子操作写的方法
// 线程8.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include<future>
#include<thread>
#include<iostream>
using namespace std;
#include<vector>
std::atomic<bool>g_ifend = false;
void mythread()
{
std::chrono::microseconds dura(1000);
while (g_ifend == false)
{
cout << "thread id = " << std::this_thread::get_id()<<"运行中" << endl;
std::this_thread::sleep_for(dura);
}
cout << "thread id = " << std::this_thread::get_id() << "运行结束" << endl;
}
int main()
{
thread myobj1(mythread);
thread myobj2(mythread);
std::chrono::microseconds dura(10000);
std::this_thread::sleep_for(dura);
g_ifend = true; //原子操作,不想被打断
myobj1.join();
myobj2.join();
cout << "程序退出" << endl;
return 0;
}
hread id = 17836运行中
thread id = 16676运行中
thread id = 16676运行中
thread id = 17836运行中
thread id = 17836运行中
thread id = 16676运行结束
thread id = 17836运行结束
程序退出
请按任意键继续. . .