从我的经验来看,似乎是结果
std::this_thread::get_id()
Run Code Online (Sandbox Code Playgroud)
在整个过程中是独一无二的:每个进程的ID都不同.
这是否由标准保证?
这曾经很好地工作(然后外星人必须攻击我的电脑):
#include <thread>
#include <iostream>
int main()
{
std::cout << std::this_thread::get_id() << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
现在它打印thread::id of a non-executing thread.
ideone.com会打印一些ID,但有趣的是可能导致我的平台出现这种行为.
$ uname -a
Linux xxx 3.13.0-77-generic #121-Ubuntu SMP Wed Jan 20 10:50:42 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
Run Code Online (Sandbox Code Playgroud)
有任何想法吗?
编辑:嗯..当我添加
std::cout << pthread_self() << std::endl;
Run Code Online (Sandbox Code Playgroud)
两行都打印相同的ID,但是当我删除它时,结果仍然是相同的 - "非执行线程".
考虑下面的情况
名称字符串作为参数移动到线程.
void start(std::string&& name) {
t = std::thread{&ThreadRunner::run, this, std::forward<std::string>(name)};
}
Run Code Online (Sandbox Code Playgroud)
线程的run函数也采用右值引用.
void run(std::string&& name) {
const auto errnum = pthread_setname_np(t.native_handle(), name.c_str());
if (errnum != 0) {
std::cout << "ERROR " << std::endl;
}
}
Run Code Online (Sandbox Code Playgroud)
线程通过start函数创建,如下所示:
ThreadRunner r;
r.start(std::string("somename"));
Run Code Online (Sandbox Code Playgroud)
问题是.run通过pthread_setname_np 在函数中访问的std :: string是否可能是垃圾,因为当范围结束时临时超出了范围?
演示
在上面的演示中,在call结束之后,是否保证somename字符串在函数中有效run?
编辑:
使用构造函数/析构函数进行演示
问题中的std :: string现在替换为a Wrap来打印所涉及的构造函数.
结果是:(第二个字段是对象的地址,第三个是线程ID)
Constructed 0x7ffc395e0ef0 140605000369984
Move Constructed 0x7ffc395e0e60 140605000369984
Move Constructed 0x177a0a0 140605000369984
Destroyed 0x7ffc395e0e60 140605000369984
Destroyed 0x7ffc395e0ef0 140605000369984
Call …Run Code Online (Sandbox Code Playgroud) 可以说我有以下课程
class A
{
public:
A()
{
my_thread=std::thread(std::bind(&A::foo, this));
}
~A()
{
if (my_thread.joinable())
{
my_thread.join();
}
}
private:
std::thread my_thread;
int foo();
};
Run Code Online (Sandbox Code Playgroud)
基本上,如果我的线程在joinable和join调用之间完成,那么my_thread.join会永远等待吗?你怎么解决这个问题?
我有一个类对象,在某些情况下只需要启动一个线程.在析构函数中,无论何时有线程都可以方便地知道.问题是,如何检测std :: thread对象是否是有效线程.
class MyClass
{
public:
~MyClass()
{
// Attention pseudocode!!!!!
if(mythread is a valid object)
mythread.join();
if(mythread was a valid object in its lifetime)
Do some stuff
}
void DoSomeStuff()
{
// May or may not create a thread
}
private:
std::thread mythread;
};
Run Code Online (Sandbox Code Playgroud) 余组Eclipse(实际上赛灵思SDK但基于Eclipse),和g ++ 4.9.2,编译其使用独立ASIO一个项目,我在属性使用-std = C++ 11 - > C/C++编译 - >设置 - >工具设置 - >其他标志,以便可以使用所有C++ 11功能进行编译.
我也在ASIO_HAS_STD_THREAD, ASIO_STANDALONEC/C++通用符号中设置等等,我希望ASIO标题std::thread代替使用pthread.但是,我仍然看到来自make的错误:
undefined reference to pthread_create,
..asio-1.10.6\include\asio\detail\impl\posix_thread.ipp
and posix_tss_ptr.hpp
Run Code Online (Sandbox Code Playgroud)
因此问题是,由于我使用C++ 11,和指定的ASIO_HAS_STD_THREAD但不是ASIO_HAS_PTHREADS,则posix_thread.ipp不应甚至包括(通过posix_thread.hpp),根据在ASIO thread.hpp:
#if !defined(ASIO_HAS_THREADS)
# include "asio/detail/null_thread.hpp"
#elif defined(ASIO_WINDOWS)
# if defined(UNDER_CE)
# include "asio/detail/wince_thread.hpp"
# else
# include "asio/detail/win_thread.hpp"
# endif
#elif defined(ASIO_HAS_PTHREADS)
# include "asio/detail/posix_thread.hpp"
#elif defined(ASIO_HAS_STD_THREAD)
# include "asio/detail/std_thread.hpp"
#else
# error Only Windows, POSIX and std::thread are supported! …Run Code Online (Sandbox Code Playgroud) 以下文本摘自《C++ 标准库:教程和参考》第二版一书中的18.2.1 \xe2\x80\xa0部分:
\n\n\n但请注意,生命周期问题也适用于全局和静态对象,因为当程序退出时,分离的线程可能仍在运行,这意味着它可能会访问已销毁或正在销毁的全局或静态对象。不幸的是,这会导致未定义的行为。
\n
据我了解,所有分离的线程将在main()结束时终止。
因此,我怀疑这种行为的原因是全局和静态对象的实际销毁顺序对于分离线程的终止而言是未指定的,即,它可能发生在分离线程终止之前、期间或之后。
\n如果对此事有任何进一步的澄清,我们将不胜感激。
\n\xe2\x80\xa0更具体地说:在标题“谨防分离线程”下的小节中下的小节中。
\n考虑这个方案,基本上创建std::thread调用该函数func()以arg作为参数:
#include <thread>
#include <iostream>
struct foo {
foo() = default;
foo(const foo&) { std::cout << "copy ctor" << std::endl; }
foo(foo&&) noexcept { std::cout << "move ctor" << std::endl; }
};
void func(foo){}
int main() {
foo arg;
std::thread th(func, arg);
th.join();
}
Run Code Online (Sandbox Code Playgroud)
我的输出是
copy ctor
move ctor
move ctor
Run Code Online (Sandbox Code Playgroud)
据我了解arg是在线程对象内部复制,然后func()作为右值传递给(移动)。所以,我期望一个副本构造和一个移动构造。
为什么要进行二次施工?
我很困惑它std::jthread::get_stop_token是如何设计的,因为它似乎有一个固有的竞争条件。
也就是说,执行线程不能简单地调用std::jthread自身(如本例所示),因为它不能保证该std::jthread对象在它开始执行时实际上已构造完毕。在我看来,对于一个线程来说get_stop_token,要使用自己的 ,它需要(至少)一个额外的事件(比如std::latch),仅用于与它自己的构造进行同步。
但是,我在网上没有看到任何有关此问题的示例或提及,因此在我看来,这可能不是预期的用法。它确实看起来相当笨重且容易出错,并且可能效率低下,因为它需要工作线程在继续之前阻塞主线程。
那么应该如何get_stop_token使用呢?
有没有一个简单的例子来说明 的正确、预期用法std::jthread::get_stop_token()?
我正在测试边缘情况,std::condition_variable并测试了使一个线程挨饿的场景。场景是有 99 个生产者和只有 1 个消费者,所有这些生产者都在 1 个最大大小的队列上工作。notify_one(达到队列最大大小后)命中消费者的概率接近 1%。因此,这意味着它将命中另一个生产者,该生产者将检查谓词,然后等待互斥体。
我预计程序会在此时挂起,但我看到的是程序尝试了尽可能多的谓词,直到最终到达消费者。如果没有消费者,则永远在所有等待线程中检查谓词。
我的问题是:标准是否定义了notify_one()将尝试通知第一个具有正谓词结果的等待线程?那么为什么它可以在没有预测的情况下与消费者一起工作(注释代码)。或者这是一个虚假的唤醒,它正在努力唤醒我的等待线程?或者是其他东西?
在 Windows 上使用 Clang 和 MSVC 进行了测试。
我的代码重现该案例:
#include <condition_variable>
#include <mutex>
#include <queue>
#include <vector>
#include <iostream>
class CVSimple
{
public:
static void test() {
std::queue<int> que;
std::mutex m;
std::condition_variable cv;
int max_size = 10;
bool working = true;
auto producer = [&]() {
while (working) {
std::unique_lock<std::mutex> lock(m);
std::chrono::milliseconds t(200);
auto predicate = [&que, &max_size]() {
if (que.size() < max_size) {
std::cout << "T";
return true; …Run Code Online (Sandbox Code Playgroud)