C++多线程【线程管控】之线程转移以及线程数量和ID

1. 移交线程归属权

std::thread支持移动语义,对于一个具体的执行线程,其归属权可以在几个std::thread实例间转移。如下所示

cpp 复制代码
  void some_function();
  void some_other_function();
  std::thread t1(some_function);
  std::thread t2 = std::move(t1);  // move thread ownership

  t1 = std::thread(some_other_function);  // assign new thread to t1

  std::thread t3;
  t3 = std::move(t2);
  t1 = std::move(t3);  // 会终止t1原来执行的线程

其中需要注意的是:

t1 = std::move(t3)操作:在转移之时,t1已经关联运行some_other_function()的线程,因此std::terminate()会被调用,终止整个程序。

也可以从函数内部返回std::thread对象以及把std::thread当做函数参数转移到函数内部,如下所示:

cpp 复制代码
std::thread f() {
  void some_function();
  return std::thread(some_function);
}

std::thread g() {
  void some_other_function(int);
  std::thread t(some_other_function, 42);
  return t;  // 返回线程对象,触发移动构造函数
}

把线程当做行数参数转移到函数内部

cpp 复制代码
// 也可以传递线程对象作为参数
void f(std::thread t);

void some_Function();
std::thread t(some_Function);
f(std::move(t));  // 传递线程对象,触发移动构造

可以把线程当做参数,给类的构造使用,即将类封装到class中。如下:

cpp 复制代码
class scoped_thread {
  std::thread t;

 public:
  explicit scoped_thread(std::thread t_) : t(std::move(t_)) {
    if (!t.joinable()) {
      throw std::logic_error("No thread");
    }
  }

  ~scoped_thread() { t.join(); }

  scoped_thread(scoped_thread const&) = delete;
  scoped_thread& operator=(scoped_thread const&) = delete;
};

// 使用方式如下
void some_other_function(int);
scoped_thread st(std::thread(some_other_function, 42));

生成多个线程,并且等待它们完成运行

cpp 复制代码
void do_work(unsigned id);
void f() {
  std::vector<std::thread> threads;
  for (unsigned i = 0; i < 20; ++i) {
    threads.emplace_back(do_work, i);
  }

  for (auto& entry : threads) {
    entry.join();
  }
}

2.在运行时选择线程数量

借用c+=标准库的std::thread::hardware_concurrency()函数

需要注意的是,硬件支持的线程数量有限,运行的线程数量不应该超出限度(超出的情况称为线程过饱和),因为线程越多,上下文切换越频繁,导致性能降低。

cpp 复制代码
// 并行版的std::accumulate()的简单实现
template <typename Iterator, typename T>
struct accumulate_block {
  void operator()(Iterator first, Iterator last, T& result) {
    result = std::accumulate(first, last, result);
  }
};

template <typename Iterator, typename T>
T parallel_accumulate(Iterator first, Iterator last, T init) {
  unsigned long const length = std::distance(first, last);
  if (!length) return init;

  unsigned long const min_per_thread = 25;
  unsigned long const max_threads =
      (length + min_per_thread - 1) / min_per_thread;

  unsigned long const hardware_threads = std::thread::hardware_concurrency();
  unsigned long const num_threads =
      std::min(hardware_threads != 0 ? hardware_threads : 2, max_threads);

  std::vector<T> results(num_threads);
  std::vector<std::thread> threads(num_threads - 1);

  Iterator block_start = first;
  for (unsigned long i = 0; i < (num_threads - 1); ++i) {
    Iterator block_end = block_start;
    std::advance(block_end, length / num_threads);
    threads[i] = std::thread(accumulate_block<Iterator, T>(), block_start,
                             block_end, std::ref(results[i]));
    block_start = block_end;
  }

  accumulate_block<Iterator, T>()(block_start, last, results[num_threads - 1]);
  for (auto& entry : threads) {
    entry.join();
  }
  return std::accumulate(results.begin(), results.end(), init);
}

3.识别线程

线程ID可以通过std::thread::id获取

当前线程I可以通过std::this_thread::get_id()获取

cpp 复制代码
std::thread::id master_thread;
void some_core_part_of_algorithm() {
  if (std::this_thread::get_id() == master_thread) {
    do_master_thread_work();
  }
  do_common_work();
}
相关推荐
renhongxia11 小时前
如何基于知识图谱进行故障原因、事故原因推理,需要用到哪些算法
人工智能·深度学习·算法·机器学习·自然语言处理·transformer·知识图谱
坚持就完事了1 小时前
数据结构之树(Java实现)
java·算法
算法备案代理1 小时前
大模型备案与算法备案,企业该如何选择?
人工智能·算法·大模型·算法备案
Monly211 小时前
Java:修改打包配置文件
java·开发语言
我命由我123451 小时前
Android 广播 - 静态注册与动态注册对广播接收器实例创建的影响
android·java·开发语言·java-ee·android studio·android-studio·android runtime
赛姐在努力.2 小时前
【拓扑排序】-- 算法原理讲解,及实现拓扑排序,附赠热门例题
java·算法·图论
island13142 小时前
CANN ops-nn 算子库深度解析:核心算子(如激活函数、归一化)的数值精度控制与内存高效实现
开发语言·人工智能·神经网络
xcLeigh2 小时前
Python入门:Python3 requests模块全面学习教程
开发语言·python·学习·模块·python3·requests
xcLeigh2 小时前
Python入门:Python3 statistics模块全面学习教程
开发语言·python·学习·模块·python3·statistics
rainbow68892 小时前
EffectiveC++入门:四大习惯提升代码质量
c++