5

I wrote the following code and am unable to understand why doesn't it prints out all the no's(i.e. 0 to -99) in threadFunc() as it does with main() thread.

#include<iostream>
#include<thread>
#include<string>
#include<mutex>
#include<chrono>

using namespace std;

mutex mu;

void threadFunc(){
    for(int i=0;i>-100;i--){
    std::this_thread::sleep_for(std::chrono::milliseconds(30)); /*delay for 30ms*/
    mu.lock();
    cout<<"Thread:  "<<i<<endl;
    mu.unlock();
    }
}

main(){

    thread t1(threadFunc);   


    for(int i=0;i<100;i++){
    mu.lock();
    cout<<"Main:  "<<i<<endl;
    mu.unlock();    
    }


    cout<<"End of Main"<<endl;  

    t1.detach();   
}

The output of the program is:

Main: 0  
Main: 1  
.  
.  
.  
Main: 99  
End of Main.  
Thread: -1 
NathanOliver
  • 171,901
  • 28
  • 288
  • 402
No Sound
  • 113
  • 1
  • 11

2 Answers2

9

Process terminates when main() exits, and all threads are killed. You observe this behavior in your program.

Detach basically says that from now on, you can't join this thread. But if you can't join it, you can't make your main() to wait until it completes (unless you use other synchronization primitives) - and thus it is happily exiting.

This is why I strongly discourage everybody from using detached threads, they are very hard to do properly.

SergeyA
  • 61,605
  • 5
  • 78
  • 137
  • Thanks for your quick response. – No Sound Apr 15 '16 at 17:05
  • Can you please explain something about how detach() works. – No Sound Apr 15 '16 at 17:15
  • 2
    @AbdulAtique, detach basically says that from now on, you can't `join` this thread. But if you can't join it, you can't make your `main()` to wait until it completes - and this is exactly what is happening in your case. The proper way is to `join` the thread before exiting `main()`. – SergeyA Apr 15 '16 at 17:17
  • @SergeyA : I couldn't have said that better myself. – Charles Apr 15 '16 at 17:28
  • Recommendation, @SergeyA : Pick that comment up and paste it, with some tweaking, into the answer. Makes for a stronger answer. – user4581301 Apr 15 '16 at 18:13
  • @user4581301, recommendation dully followed :) – SergeyA Apr 15 '16 at 18:39
  • @SergeyA, Thanks for your answer, I was trying to figure out why all my `cout`s don't work in detached thread when `main` completes, but didn't find the answer for a long, now things are clear! I thought that threads created in main continue to live in background, now I know that all threads created by the program are killed when main completes. – Vadixem Jan 16 '20 at 21:27
  • @VadimSorochan glad it was useful! – SergeyA Jan 17 '20 at 17:59
6

The detach function prevents an exception from being thrown when the thread object goes out of scope. Usually, you would want to call join but if you don't want to block the execution you need to call detach. However, you probably need to use another synchronization mechanism to make sure everything is fine if the thread is still running when main is ready to exit. See the following contrived example.

Example Code

#include <atomic>
#include <chrono>
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <string>
#include <thread>

std::mutex mu;
std::condition_variable cv;
bool finished = false;

void threadFunc()
{
    for (int i = 0; i < 5; ++i)
    {
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
        std::unique_lock<std::mutex> lock(mu);
        std:: cout << "Thread:  " << (0 - i) << "\n";
    }

    std::unique_lock<std::mutex> lock(mu);
    finished = true;
    cv.notify_one();
}

int main()
{
    {
        std::thread t1(threadFunc);
        t1.detach(); // Call `detach` to prevent blocking this thread

    } // Need to call `join` or `detach` before `thread` goes out of scope

    for (int i = 0; i < 5; ++i)
    {
        std::unique_lock<std::mutex> lock(mu);
        std::cout << "Main:  " << i << "\n";
    }

    std::cout << "End of Main\n";

    std::unique_lock<std::mutex> lock(mu);
    cv.wait(lock, [&finished]() { return finished; });

    return 0;
}

Example Output

Main:  0
Main:  1
Main:  2
Main:  3
Main:  4
End of Main
Thread:  0
Thread:  -1
Thread:  -2
Thread:  -3
Thread:  -4

Live Example

Again, the above is a contrived example and in your case you could more easily use join instead of detach before allowing main to return.

James Adkison
  • 9,412
  • 2
  • 29
  • 43