关于std::future成员函数wait_for()

一、关于std::future成员函数wait_for()

1.1 关于std::future_status
std::future_status是一个枚举类型,其值有三:

// ENUM future_status
enum class future_status { // names for timed wait function returnsready,timeout,deferred//延迟执行,当std::async()第一个参数为std::lanuch::deferred时生效。
};

1.2 wait_for():
返回值类型为future_status,该函数将本线程阻塞在当前,并等待一段时间,后继续执行,若在等待时间内wait_for()绑定线程执行完毕,则返回ready,未执行完毕则返回timeout

int myThread1(int arg)
{cout << arg << endl;cout << "myThread()  START..." << "   thread_id:" << std::this_thread::get_id() << endl;Sleep(5000);cout << "myThread()  END..." << "   thread_id:" << std::this_thread::get_id() << endl;return 5;
}int main()
{cout << "main thread id:" << std::this_thread::get_id() << endl;std::future<int>result = std::async(myThread1, 3);cout << "continue..." << endl;//枚举类型std::future_status status = result.wait_for(std::chrono::seconds(3));//设置等待3s,根据设置等待时间与子线程执行消耗时间得到返回值。决定程序在当前行阻塞时间。if (status == std::future_status::timeout)//子线程还没执行完{cout << "timeout..." << endl;//cout << result.get() <}else if (status == std::future_status::ready)//子线程已执行完{cout << "ready..." << endl;//cout << result.get() << endl;}return 0;
}

关于枚举类型值deferred:

std::future<int>result = std::async(std::launch::deferred,myThread1, 3);

当std::async()第一个参数为std::lanuch::deferred时生效。此时线程不在阻塞在wait_for()处,而是继续执行直到遇见属于该future对象的get()

	else if (status==std::future_status::deferred){cout << "deferred act" << endl;cout << result.get();}

注意:无论std::async()是否延迟执行,异步线程都将会指向完程序才能结束,三种结束方式:

  • 阻塞在wait_for()处等待异步线程结束
  • 阻塞在get()处等待异步线程结束
  • 阻塞在return 0;处等待异步线程结束

get()函数只能使用一次,因为get()函数的设计是一个移动语义,相当于将future对象中的值转移到了get()调用者中,所以再次get()就报告了异常。

二、std::shared_future

也是类模板,其get()函数复制数据。

在实际开发中,有时候某线程的值不止被一个线程所需要,而get()却只能只用一次,这时可以通过std::shared_future达到多次通过get()获取值的目的:

	std::future<int>myf = mypt.get_future();std::shared_future<int>myf_s(myf.share());std::thread t2(mythread1,std::ref(myf_s));t2.join();auto mysf = myf_s.get();cout << mysf << "   -" << endl;cout << "---------------" << endl;auto mysf2 = myf_s.get();cout << mysf2 << "   -" << endl;

如上,用std::future初始化std::shared_future对象,通过std::shared_future即可多次调用get()获取线程返回。

也可不通过std::future连接std::shared_futurepackaged_task对象:

//原:std::future<int>myf = mypt.get_future();std::shared_future<int>myf_s(myf.share());
//简化:std::shared_future<int>myf_s = mypt.get_future();

三、原子操作std::atomic
std::atomic来代表原子操作,是个类模板。其实std::atomic是用来封装某个类型的值的

原子操作: 在多线程中不会被打断的程序执行片段。

效率上: 原子操作要比互斥量的方式效率要高。

  • 互斥量的加锁一般是针对一个代码段,而原子操作针对的一般都是一个变量。

  • 原子操作,一般都是指* 不可分割的操作 * ;也就是说这种操作状态要么是完成的,要么是没完成的,不可能出现半完成状态。

注意使用时需要添加#include 头文件

实例1:计算自增后的值:

std::atomic<int> g_count = 0;void myThread()
{for (size_t i = 0; i < 10000000; i++)g_count++;
}int main()
{std::thread t1(myThread);std::thread t2(myThread);t1.join();t2.join();cout << g_count << endl;return 0;
}

实例2:判断线程是否结束

std::atomic<bool> g_ifend = false;void myThread()
{std::chrono::milliseconds dura(1000);while (g_ifend==false){cout << "thread is working" << "---  " << std::this_thread::get_id() << endl;std::this_thread::sleep_for(dura);//Sleep(1);}cout << "----- end -----" << "---  " << std::this_thread::get_id() << endl;
}int main()
{std::thread t1(myThread);std::thread t2(myThread);//Sleep(5);std::chrono::milliseconds dura1(5000);std::this_thread::sleep_for(dura1);g_ifend = true;t1.join();t2.join();return 0;
}

原子操作一般用于计数或者统计(如数据包的累计发送或者接受数目),如果多个线程一起统计,不使用原子操作会导致统计发生混乱。

更多内容欢迎参见我的个人网站:http://www.huazhige.online/


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部