C++11std::thread的使用-创新互联

std::thread
  • std::thread 构造函数
  • std::thread 赋值操作
  • std::thread其他成员函数
    • `get_id`: 获取线程 ID
    • `joinable`: 检查线程是否可被 join
    • `detach`: Detach 线程
    • `join`: Detach 线程
    • `swap`: Swap 线程
    • `native_handle:` 返回 native handle
    • `hardware_concurrency` \[static]
  • std::this_thread 命名空间中相关辅助函数
  • std::thread的可联结性
  • std::thread 对象析构

员工经过长期磨合与沉淀,具备了协作精神,得以通过团队的力量开发出优质的产品。创新互联建站坚持“专注、创新、易用”的产品理念,因为“专注所以专业、创新互联网站所以易用所以简单”。公司专注于为企业提供成都网站设计、成都做网站、微信公众号开发、电商网站开发,小程序定制开发,软件按需策划等一站式互联网企业服务。std::thread 构造函数
//默认构造函数  
thread() noexcept;
//初始化构造函数  
templateexplicit thread(Fn&& fn, Args&&... args);
//拷贝构造函数 [deleted]  
thread(const thread&) = delete;
//Move 构造函数  
thread(thread&& x) noexcept;

  • 默认构造函数,创建一个空的std::thread执行对象。
  • 初始化构造函数,创建一个std::thread对象,该std::thread对象可被joinable,新产生的线程会调用fn函数,该函数的参数由args给出。
  • 拷贝构造函数(被禁用),意味着std::thread对象不可拷贝构造。
  • Move 构造函数,move 构造函数(move 语义是 C++11 新出现的概念,详见附录),调用成功之后x不代表任何std::thread执行对象。
  • 📌注意:可被joinablestd::thread对象必须在他们销毁之前被主线程join或者将其设置为detached.

std::thread 赋值操作
//Move 赋值操作  
thread& operator=(thread&& rhs) noexcept;
//拷贝赋值操作 [deleted]  
thread& operator=(const thread&) = delete;

  • Move 赋值操作(1),如果当前对象不可joinable,需要传递一个右值引用(rhs)给move赋值操作;如果当前对象可被joinable,则会调用terminate() 报错。
  • 拷贝赋值操作(2),被禁用,因此std::thread对象不可拷贝赋值。
  • 示例
#include#include#include// std::chrono::seconds
 #include// std::cout
 #include// std::thread, std::this_thread::sleep_for

 void thread_task(int n) { std::this_thread::sleep_for(std::chrono::seconds(n));
     std::cout<< "hello thread "<< std::this_thread::get_id()<< " paused "<< n<< " seconds"<< std::endl;
 }

 int main(int argc, const char *argv[])
 { std::thread threads[5];
     std::cout<< "Spawning 5 threads...\n";
     for (int i = 0; i< 5; i++) { threads[i] = std::thread(thread_task, i + 1);
     }
     std::cout<< "Done spawning threads! Now wait for them to join\n";
     for (auto& t: threads) { t.join();
     }
     std::cout<< "All threads joined.\n";

     return EXIT_SUCCESS;
 }

std::thread其他成员函数get_id: 获取线程 ID
  1. 如果该std::thread是joinable状态(joinable状态后面会提到),那么就返回一个独一无二的(unique)的当前std::thread的id(std::thread::id).
  2. 如果该std::thread是not joinable状态,返回std::thread::id();
joinable: 检查线程是否可被 join

该函数返回一个bool值:

  1. 如果当前std::thread对象是default-constructor构造出来的返回false.
  2. 如果当前std::thread对象被移动到了其他std::thread对象返回false.
  3. 如果当前std::thread对象的detach()和join()被调用过了返回false.

检查当前的线程对象是否表示了一个活动的执行线程,由默认构造函数创建的线程是不能被 join 的。
另外,如果某个线程 已经执行完任务,但是没有被 join 的话,该线程依然会被认为是一个活动的执行线程,因此也是可以被 join 的。

detach: Detach 线程

Detach 线程。 将当前线程对象所代表的执行实例与该线程对象分离,使得线程的执行可以单独进行。一旦线程执行完毕,它所分配的资源将会被释放。


调用 detach 函数之后:

  • *this不再代表任何的线程执行实例。
  • joinable() == false
  • get_id() == std::thread::id()

📌另外,如果出错或者joinable() == false,则会抛出std::system_error

join: Detach 线程

block(阻塞)调用join()的线程,直到std::thread所在的线程完成,与此同时std::thread独显被设置为not joinable.

swap: Swap 线程

Swap 线程,交换两个线程对象所代表的底层句柄(underlying handles)。

native_handle:返回 native handle

返回 native handle(由于 std::thread 的实现和操作系统相关,因此该函数返回与 std::thread 具体实现相关的线程句柄,例如在符合 Posix 标准的平台下(如 Unix/Linux)是 Pthread 库)。

  • 示例
#include#include#include#include#includestd::mutex iomutex;
 void f(int num)
 {std::this_thread::sleep_for(std::chrono::seconds(1));

  sched_param sch;
  int policy; 
  pthread_getschedparam(pthread_self(), &policy, &sch);
  std::lock_guardlk(iomutex);
  std::cout<< "Thread "<< num<< " is executing at priority "
 << sch.sched_priority<< '\n';
 }

 int main()
 {std::thread t1(f, 1), t2(f, 2);

   sched_param sch;
   int policy; 
   pthread_getschedparam(t1.native_handle(), &policy, &sch);
   sch.sched_priority = 20;
   if(pthread_setschedparam(t1.native_handle(), SCHED_FIFO, &sch)) {   std::cout<< "Failed to setschedparam: "<< std::strerror(errno)<< '\n';
   }

   t1.join();
   t2.join();
 }
hardware_concurrency[static]

检测硬件并发特性,返回当前平台的线程实现所支持的线程并发数目,但返回值仅仅只作为系统提示(hint)。

  • 示例
#include#includeint main() {unsigned int n = std::thread::hardware_concurrency();
   std::cout<< n<< " concurrent threads are supported.\n";
 }
std::this_thread 命名空间中相关辅助函数
  • get_id:返回一个独一无二的当前线程的ID(一般也就是unsigned int类型).
  • yield: 使正在处于运行状态的该线程,回到可运行状态,以允许其他具有相同优先级的线程获得先执行的机会。但是很有可能该线程刚刚回到可执行状态又被再次执行。
  • sleep_until: 线程休眠至某个指定的时刻(time point),该线程才被重新唤醒
  • sleep_for: 线程休眠某个指定的时间片(time span),该线程才被重新唤醒,不过由于线程调度等原因,实际休眠时间可能比 sleep_duration 所表示的时间片更长。
std::thread的可联结性

一个 std::thread 对象只可能处于可联结或不可联结两种状态之一。即 std::thread 对象是否与某个有效的底层线程关联。


  • 可联结:当线程可运行、已经运行或处于阻塞时是可联结的。但如果某个底层线程已经执行完任务,但是没有被 join 的话,该线程依然会被认为是一个活动的执行线程,仍然处于 joinable 状态。
  • 不可联结:不带参构造的std::thread对象为不可联结,因为底层线程还没创建;已经移动的std::thread对象为不可联结;已经调用join或detach的对象为不可联结状态。
  • joinable():判断是否可以成功使用join()或者detach(),返回true 表示可以,否则返回false
std::thread 对象析构

std::thread 对象析构时,会先判断joinable(),如果可联结,则程序会直接被终止(terminate)。
因此,在创建 thread 对象以后,要在随后的某个地方显式地调用 join 或 detach 以便让std::thread处于不可联结状态。

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


名称栏目:C++11std::thread的使用-创新互联
路径分享:http://csdahua.cn/article/ipoeo.html
扫二维码与项目经理沟通

我们在微信上24小时期待你的声音

解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流