在C ++ 11中,有std::this_thread::get_id()
我可以用来获取线程的std::thread::id
标识符。该标准说:
30.3.1.1
- thread :: id类型的对象为每个执行线程提供唯一的标识符,为所有线程对象提供单个不同的值 不代表执行线程(30.3.1)。每个线程 执行具有关联的thread :: id对象,该对象不等于 thread :: id任何其他执行线程的对象,但不是 等于任何不包含std :: thread对象的thread :: id对象 代表执行线程。
- thread :: id应该是一个普通可复制的类(第9条)。该库可以重用终止线程的thread :: id的值 不能再加入了。
我的问题恰好是关于新线程B与旧线程A具有相同的id
的情况:线程B会“看到”线程A所做的更改吗?
更具体地考虑以下情况:
线程A这样做:
owner.store(std::this_thread::get_id()); //store A's 'id'
...some work...
owner.store(std::thread::id(),std::memory_order_relaxed); // clear
线程B确实:
assert(owner.load(std::memory_order_relaxed) != std::this_thread::get_id());
这个断言会成立吗?
线程A中的owner.load
和线程B中的最后owner.store
是有意“放松”的,因此,除了我认为的那个之外,两者之间没有明显的“同步”关系。问题。
答案 0 :(得分:0)
我的问题恰恰是关于新线程B具有 与旧线程A相同的ID :线程B将“查看所做的更改 通过“线程A?
-因此,您的规定与以下情况有关:线程A
肯定终止(即无法再加入)并且线程B
已经启动,可能会重用线程A
'的ID。
在这种情况下(线程A
和B
是后续线程,而不是并发线程),断言将保持有效-即使其ID可能相同,到线程B启动时,所有者的存储肯定会清空(通过终止线程A
来保证)
更新:感谢@Yakk - Adam Nevraumont
的评论-这是我对写的忽略->在relaxed order
下的读操作-以上声明是错误的!也就是说,在线程A
的最后一个操作中的内存提交将与线程B
的读取异步,因此断言可能不成立! (很抱歉造成混乱)
否则(线程A
和B
是并发的),它们将永远不会获得相同的ID,因此断言也将保持不变。
答案 1 :(得分:0)
[1]考虑到标准中写的内容,并假设唯一性是在考虑物理时间的情况下概念化的,即在给定的时间没有两个线程id可以相同,那么为了确保标准要求,系统必须确保A的结尾发生在B的开始之前。
[2]搁置的结束发生在该线程开始处启动的函数体执行之后,而线程的开始发生在此启动函数主体执行之前。如[basic.exec] / 11中所指定:
在调用一个函数时(无论该函数是否是内联的),与任何参数表达式或指定所调用函数的后缀表达式关联的每个值计算和副作用都将在执行每个表达式或语句之前进行排序。被调用函数的主体。对于每个函数调用F,对于在F内发生的每个求值A和在F中不发生但在同一线程上并且作为同一信号处理程序(如果有)的一部分进行求值的每个求值B,A都在B之前排序。或B在A之前排序。
[1]和[2]表示线程A中的每个计算都发生在线程B中的任何计算之前。