Threads
Thread IDs
std::thread::ThreadId is an opaque, process-unique identifier assigned by the Rust standard library to each thread upon creation or first inspection (thread::current().id()).
Guarantees of ThreadId vs. OS Thread IDs (pthread_t / TID)
A critical distinction between Rust's std::thread::ThreadId and operating-system thread handles (pthread_t on Unix or DWORD thread IDs on Windows) is non-reuse:
- OS thread IDs can be recycled by the operating system kernel immediately after a thread exits.
- Rust's
ThreadIdis strictly monotonic (64-bit counter) and is NEVER reused for the entire lifetime of the process, even after the thread that owned thatThreadIdterminates!
| Property | std::thread::ThreadId |
OS Thread Handle / TID |
|---|---|---|
| Uniqueness guarantee | Never reused within the lifetime of the process | Recycled by OS kernel after thread termination |
| Trait implementations | Copy, Clone, Eq, PartialEq, Hash, Debug, Send, Sync |
Platform-specific FFI type (std::os::unix::thread::RawPthread) |
Usable as a HashMap key? |
Yes (HashMap<ThreadId, State>) |
Requires raw integer conversion and cleanup on thread exit |
| How to obtain | thread::current().id() or join_handle.thread().id() |
JoinHandleExt::as_pthread_t() / OS syscall |
Using ThreadId for Per-Thread Attribution and Re-Entrancy Detection
Because ThreadId implements Copy, Eq, and Hash, it is ideal for tagging log lines, attributing metrics per worker thread in a HashMap<ThreadId, Metrics>, or detecting whether the current thread already holds a custom lock (owner_tid == Some(thread::current().id())):
use std::collections::HashMap;
use std::sync::Mutex;
use std::thread::{self, ThreadId};
fn main() {
let work_counts: Mutex<HashMap<ThreadId, u32>> = Mutex::new(HashMap::new());
thread::scope(|s| {
for _ in 0..3 {
s.spawn(|| {
let my_tid = thread::current().id();
for _ in 0..5 {
*work_counts.lock().unwrap().entry(my_tid).or_insert(0) += 1;
}
});
}
});
let map = work_counts.lock().unwrap();
println!("distinct ThreadIds recorded: {}", map.len());
for (tid, count) in &*map {
println!(" {:?} completed {} tasks", tid, count);
}
}
distinct ThreadIds recorded: 3
ThreadId(2) completed 5 tasks
ThreadId(3) completed 5 tasks
ThreadId(4) completed 5 tasks