简体   繁体   English

std :: thread什么时候执行线程?

[英]std::thread when is thread executed?

I've ran through some threading tutorials but am curious about one thing. 我已经浏览了一些线程教程,但我很好奇一件事。

std::thread Child([](){ std::cout << "When am I executed?" << std::endl << std::endl; });

//Some other code

Child.join();

//I'm guessing now my thread would be running

Is the thread being executed when I call join() or is it being run sometime between when create the thread and when I call join? 线程是在我调用join()时执行还是在创建线程和调用join之间的某个时间运行? If it is executed when join() is called, just to check my understanding, it tells that portion to execute and your program continues on the main thread and eventually the child thread has done some work on the same memory the main thread is using? 如果在调用join()时执行它,只是为了检查我的理解,它告诉要执行的部分,你的程序继续在主线程上,最终子线程在主线程使用的同一内存上做了一些工作?

If I wanted to create a wrapper for a generic class, I would want to do something like below but I can't seem to figure it out completely. 如果我想为泛型类创建一个包装器,我会想做类似下面的事情,但我似乎无法完全弄明白。 I'm confused with managing the threads in terms of memory. 我对在内存方面管理线程很困惑。

class Sync {
private:
    int val;

public:
    Sync() : val(0) {}
    void Inc() {val++}
    int Value() { return val; }
};

class Async {
private:
    Sync Foo;
    std::mutex mtx;
    std::vector<std::thread*> Children;
public:
    //I would need a new thread each time I called Inc
    void Inc() { 
        Children.push_back(new std::thread([&]() {
            mtx.lock();
            Foo.Inc();
            mtx.unlock();
        }));


    }
    //But how do I know when it is safe to delete Child?  
    int Value() { 
        for(auto& thds : Children) {
            thds->join();
            delete thds; 
        }
        Children.clear();
        return Foo.Value(); }
};

I was considering that an appropriate location might be at the end of the thread function because Child would no longer be needed but what happens if you try to destroy the thread from within itself? 我正在考虑一个合适的位置可能在线程函数的末尾,因为不再需要Child但是如果你试图从内部破坏线程会发生什么? I'm guessing it will be as much of a bad idea as it sounds. 我猜这听起来不是一个坏主意。 How can I know when it's okay to delete my thread? 我怎么知道什么时候可以删除我的线程? Is there a better approach? 有更好的方法吗?

Modified above code to reflect suggestions from below. 修改上面的代码以反映下面的建议。

I now realize what the tutorials were talking about in regards to throwing an exception so I should use a mutex guard and not mtx.lock() I guess. 我现在意识到教程正在讨论关于抛出异常的内容,所以我应该使用互斥锁而不是mtx.lock()我想。

The purpose of join is to, essentially, wait for the thread to complete. 的目的join是,本质上,等待线程完成。 So once Child->join(); 所以一旦Child->join(); returns, your thread has completed. 返回,你的线程已经完成。 Of course, you could also do Child->join() in the destructor [or at some other point, just make sure it is called at some point]. 当然,您也可以在析构函数中执行Child->join() [或者在某些其他方面,确保在某些时候调用它]。

Note that, the thread will start running at some point between the time it actually created, and the end of join. 请注意,线程将在实际创建的时间和连接结束之间的某个时刻开始运行。 There is no way of telling when that will happen. 无法确定何时会发生这种情况。 If you have lots of threads already running on the system, the time will be distributed between all threads, and your thread may not run for several seconds. 如果系统上已经运行了很多线程,则时间将在所有线程之间分配,并且您的线程可能无法运行几秒钟。 On the other hand, if there is a CPU sitting there "twiddling it's fingers", it could quite possibly start before the main thread is out of the new std::thread(...) construction [because std::thread won't return until the thread has been properly created, and some data is being stored in the thread object, so the thread may well have completed by the time you get to Child->join() . 另一方面,如果有一个CPU坐在那里“弄乱它的手指”,它很可能在主线程超出new std::thread(...)构造之前启动[因为std::thread won' t返回,直到线程被正确创建,并且一些数据存储在线程对象中,因此在到达Child->join()时线程可能已经完成。 There is no way to tell which of these options it is without knowing what state the system is in. 如果不知道系统处于什么状态,就无法确定这些选项中的哪一个。

The operating system matters, but it is rather universal. 操作系统很重要,但它相当普遍。 The thread gets scheduled to execute. 线程被安排执行。 When the operating system gets around to actually make it run is entirely unpredictable. 当操作系统到处实际运行时,完全无法预测。 You'll have decent odds for "quickly" on a machine with multiple cores, universally available today. 你可以在拥有多个内核的机器上“快速”获得不错的赔率,这在今天是普遍可用的。

thread::join() just ensures that the thread finished executing. thread :: join()只是确保线程完成执行。 You would never actually write code like this, it is completely pointless to start a thread and then wait for it to complete. 永远不会真正编写这样的代码,启动一个线程然后等待它完成是完全没有意义的。 Might as well execute the thread's code directly. 也可以直接执行线程的代码。 Same outcome without bogging down the operating system with creating a thread. 通过创建线程而不会影响操作系统的结果相同。

You cannot know in which order or on which core your thread will be run. 您无法知道您的线程将以何种顺序或核心运行。

A posix thread is basically treated by linux as a process sharing its heap with another one. 一个posix线程基本上被linux视为一个与另一个共享其堆的进程。 The kernel will schedule them and decide which core to use. 内核将安排它们并决定使用哪个核心。 For instance look at the generated (protected) assembly you will not see any "multicore/multithread programming", as this is done at kernel level. 例如,查看生成的(受保护的)程序集,您将看不到任何“多核/多线程编程”,因为这是在内核级别完成的。

This is why function such as join, and artifacts such as mutex/semaphores exists. 这就是为什么存在诸如连接之类的函数和诸如互斥锁/信号量之类的工件的原因。 To take care of race condition and other related stuffs. 照顾比赛条件和其他相关的东西。

Is the thread being executed when I call join() or is it being run sometime between when create the thread and when I call join? 线程是在我调用join()时执行还是在创建线程和调用join之间的某个时间运行?

The thread is executed (started) after you create the thread, depending on the available resources that might take some time. 在创建线程后执行(启动)线程,具体取决于可能需要一些时间的可用资源。 The join() method waits(blocks) until the thread has finished its work. join()方法等待(阻塞),直到线程完成其工作。

A suggestion: i would not name the variable to the Sync object This , its confusing, since there exists the this keyword. 一个建议:我不会将变量命名为Sync对象This ,令人困惑,因为存在this关键字。

You can safely delete the std::thread object after calling join() in Async::Inc() , plus you don't need to store the reference as a member variable, it's only used in that function. 您可以在Async::Inc()调用join()之后安全地删除std::thread对象,而且您不需要将引用存储为成员变量,它只在该函数中使用。

You might also take a look at the <atomic> header, std::atomic<int> or std::atomic_int . 您还可以查看<atomic>标头, std::atomic<int>std::atomic_int

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM