文章

线程标识

std::thread::id唯一标识线程,支持比较,可作为容器键,默认值表示无线程。

线程标识

线程标识

获取线程标识的两种方式

通过 std::thread 对象获取

1
2
std::thread t([]{ /* do something */ });
std::thread::id id = t.get_id();
  • 如果 std::thread 没有绑定线程,get_id() 返回默认构造的 std::thread::id,代表“无线程”。

  • “没有绑定线程”的情况举例:

    • std::thread 对象刚被默认构造,没启动线程:

      1
      
      std::thread t;  // 空线程对象,没有启动任何线程
      
    • 线程执行完毕且被 join() 后,线程对象与线程解绑:

      1
      2
      
      std::thread t([]{ /*...*/ });
      t.join();  // 线程执行完毕,t 不再关联任何线程
      
    • 线程对象被移动后,原对象不再关联线程:

      1
      2
      3
      
      std::thread t1([]{ /*...*/ });
      std::thread t2 = std::move(t1);
      // 现在 t1 是空的,没有绑定线程,t2 关联线程
      
  • std::thread::id() 是默认构造的线程ID,和 t.get_id() 返回值相等,说明 t 是空的

    1
    2
    3
    4
    5
    6
    
    std::thread t;  // 默认构造,没有启动线程
    auto id = t.get_id();
      
    if (id == std::thread::id()) {
        std::cout << "t没有关联任何线程\n";
    }
    

通过当前线程调用

1
std::thread::id id = std::this_thread::get_id();  // 需要包含 <thread>

线程标识的比较与用法

  • std::thread::id 可拷贝、赋值、比较(==、!=、<、> 等),可以用于排序。

  • 也可以用于作为 有序/无序容器(如 std::map, std::unordered_map 的键:

    1
    2
    
    std::unordered_map<std::thread::id, ThreadData> threadDataMap;
    threadDataMap[std::this_thread::get_id()] = someData;
    
  • 标准库提供 std::hash<std::thread::id>,使其可用于哈希容器。

典型应用场景

示例 1:主线程做不同操作

某些并行任务中,主线程可能要处理与其他线程不同的逻辑,可以通过线程 ID 判断:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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();  // 所有线程通用任务
}

int main() {
    master_thread = std::this_thread::get_id();
    std::thread t1(some_core_part_of_algorithm);
    std::thread t2(some_core_part_of_algorithm);
    some_core_part_of_algorithm();  // 主线程执行
    t1.join();
    t2.join();
}

示例 2:线程 ID 作为权限标识

线程 ID 可以存入结构体,用于判断某个操作是否“被允许”或“被要求”:

1
2
3
4
5
6
7
8
9
10
11
12
13
struct ThreadGuard {
    std::thread::id owner;

    ThreadGuard() : owner(std::this_thread::get_id()) {}

    void do_work() {
        if (std::this_thread::get_id() == owner) {
            std::cout << "Allowed to work\n";
        } else {
            std::cout << "Not allowed\n";
        }
    }
};

示例 3:线程 ID 作为线程信息索引键

1
2
3
4
5
6
std::map<std::thread::id, std::string> threadNames;

void threadFunction(const std::string& name) {
    threadNames[std::this_thread::get_id()] = name;
    std::cout << "Hello from " << threadNames[std::this_thread::get_id()] << "\n";
}

线程 ID 的输出

可将线程 ID 输出到标准流(如 std::cout),以便调试:

1
std::cout << "Current thread ID: " << std::this_thread::get_id() << "\n";

注意:线程 ID 的具体输出形式是 实现相关的,但 相同线程必须输出相同的 ID

总结

特性说明
类型std::thread::id
默认值std::thread::id() 表示“无线程”
获取方式t.get_id() / std::this_thread::get_id()
可用于比较/排序支持 <, ==, != 等运算符
可用于容器键std::map, std::unordered_map
常见用途判断线程身份、区分主从线程、存储线程信息等
可输出std::cout << std::this_thread::get_id()
本文由作者按照 CC BY 4.0 进行授权