What does std::thread.join() do? - c++

By definition from C++ reference:
Blocks the current thread until the thread identified by *this finishes its execution.
So does this mean when using .join(), there's no need to mutex.lock() when that thread calls some function? I'm new to mutual exclusion and threading, so I'm kind of confused.
Note: I've found a book
C++ Concurrency in Action and I am reading the book. It is very well written for a beginner on multithreading like me.
Thank you all for the help.

You still need mutexes and conditions. Joining a thread makes one thread of execution wait for another thread to finish running. You still need mutexes to protect shared resources. It allows main() in this example to wait for all threads to finish before quitting itself.
#include <iostream>
#include <thread>
#include <chrono>
#include <mutex>
using namespace std;
int global_counter = 0;
std::mutex counter_mutex;
void five_thread_fn(){
for(int i = 0; i<5; i++){
counter_mutex.lock();
global_counter++;
counter_mutex.unlock();
std::cout << "Updated from five_thread" << endl;
std::this_thread::sleep_for(std::chrono::seconds(5));
}
//When this thread finishes we wait for it to join
}
void ten_thread_fn(){
for(int i = 0; i<10; i++){
counter_mutex.lock();
global_counter++;
counter_mutex.unlock();
std::cout << "Updated from ten_thread" << endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
//When this thread finishes we wait for it to join
}
int main(int argc, char *argv[]) {
std::cout << "starting thread ten..." << std::endl;
std::thread ten_thread(ten_thread_fn);
std::cout << "Running ten thread" << endl;
std::thread five_thread(five_thread_fn);
ten_thread.join();
std::cout << "Ten Thread is done." << std::endl;
five_thread.join();
std::cout << "Five Thread is done." << std::endl;
}
Note that the output might look like this:
starting thread ten...
Running ten thread
Updated frUopmd atteend_ tfhrroema df
ive_thread
Updated from ten_thread
Updated from ten_thread
Updated from ten_thread
Updated from ten_thread
Updated from five_thread
Updated from ten_thread
Updated from ten_thread
Updated from ten_thread
Updated from ten_thread
Updated from ten_thread
Updated from five_thread
Ten Thread is done.
Updated from five_thread
Updated from five_thread
Five Thread is done.
Since std::cout is a shared resource access and use of it should also be mutex protected too.

join() stops current thread until another one finishes. mutex stops current thread until mutex owner releases it or locks right away if it isn't locked. So these guys are quite different

It blocks the current thread until the execution of the thread is completed on which join() is called.
If you do not specify join() or dettach() on the thread then it will result in runtime error as the main/current thread will complete its execution and the other thread created will be still running.

std::thread.join has three functions I can think of off-hand and some others:
a) Encourages continual creating/terminating/destroying of threads, so hammering performance and increasing the probabilty of leaks, thread-runaway, memory-runaway and general loss-of-control of your app.
b) Stuffs GUI event-handlers by enforcing unwanted waits, resulting in unresponsive 'hourglass apps' that your customers will hate.
c) Causes apps to fail to shutdown because they are waiting for the termination of an unresposive, uninterruptible thread.
d) Other bad things.
I understand that you are new to multithreading, and I wish you the best with it. Also, consider that I've had a lot of Adnams Broadside tonight, but:
Join(), and it's friends in other languages like TThread.WaitFor, (Delphi), are to efficient multithreading like Windows ME was to operating systems.
Please try hard to progress and come to understand other multithreaded concepts - pools, tasks, app-lifetime threads, inter-thread comms via producer-consumer queues. In fact, almost anything except Join().

Related

Mutex locking and unlocking time difference

I'm new to multithread programming. I have a simple testing program:
#include <mutex>
#include <thread>
#include <iostream>
int main(){
std::mutex mtx;
std::thread t1([&](){
while (true){
mtx.lock();
std::cout << 1 << "Hello" << "\n";
mtx.unlock();
}
});
std::thread t2([&](){
while (true){
mtx.lock();
std::cout << 2 << "Hello" << "\n";
mtx.unlock();
}
});
t1.join();
t2.join();
}
This is a pretty simple program, and it prints "1Hello" and "2Hello" in a random pattern, which implies that the mutex is unlocked by one and then acquired by the other and executed, in some random pattern.
Is it specified behavior in standard, that is, will a implementation guarantee that it won't stick to t1? And if not, how do I avoid it?
There should be no guarantee of who will be running. If you can set the priority of one thread higher than the other, then you can guarantee with this code that only the highest priority thread will be running.
What is the actual problem? The problem is that this code uses multi-threading in the worst possible way. This is quite an achievement and not really bad because it is an exercise. It asks the threads to run continuously, it locks while doing long actions and only unlocks for the next loop, so there is actually no parallelism, only a battle for the mutex.
How can this be solved? Let the threads do some background action and then stop or let the threads wait for a condition are at least let the threads sleep once in a while AND let the threads run as independent as possible and not block others while doing potentially a long action.
Edit (small clarification): while this code is using multi-threading in the worst possible way, it is a nice and clean example on how to do it.

Boost w/ C++ - Curious mutex behavior

I'm experimenting with Boost threads, as it's to my knowledge I can write a multi-threaded Boost application and compile it in Windows or Linux, while pthreads, which I'm more familiar with, is strictly for use on *NIX systems.
I have the following sample application, which is borrowed from another SO question:
#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/bind.hpp>
#include <iostream>
#define NAP_DURATION (10000UL) // 10ms
boost::mutex io_mutex;
void count(int id)
{
for (int i = 0; i < 1000; ++i)
{
boost::mutex::scoped_lock lock(io_mutex);
std::cout << "Thread ID:" << id << ": " << i << std::endl;
if (id == 1)
{
std::cout << "I'm thread " << id << " and I'm taking a short nap" << std::endl;
usleep(NAP_DURATION);
}
else
{
std::cout << "I'm thread " << id << ", I drink 100 cups of coffee and don't need a nap" << std::endl;
}
std::cout << "Thread ID:" << id << ": " << i << std::endl;
boost::thread::yield();
}
}
int main(int argc, char* argv[])
{
boost::thread thrd1( boost::bind(&count, 1));
boost::thread thrd2( boost::bind(&count, 2));
thrd1.join();
thrd2.join();
return 0;
}
I installed Boost on my Ubuntu 14.04 LTS system via:
sudo apt-get install libboost-all-dev
And I compile the above code via:
g++ test.cpp -lboost_system -lboost_thread -I"$BOOST_INLCUDE" -L"$BOOST_LIB"
I've run into what appears to be some interesting inconsistencies. If I set a lengthy NAP_DURATION, say 1 second (1000000) it seems that only thread 1 ever gets the mutex until it completes its operations, and it's very rare that thread 2 ever gets the lock until thread 1 is done, even when I set the NAP_DURATION to be just a few milliseconds.
When I've written similar such applications using pthreads, the lock would typically alternate more or less randomly between threads, since another thread would already be blocked on the mutex.
So, to the question(s):
Is this expected behavior?
Is there a way to control this behavior, such as making scoped locks behave like locking operations are queued?
If the answer to (2) is "no", is it possible to achieve something similar with Boost condition variables and not having to worry about lock/unlock calls failing?
Are scoped_locks guaranteed to unlock? I'm using the RAII approach rather than manually locking/unlocking because apparently the unlock operation can fail and throw an exception, and I'm trying to make this code solid.
Thank you.
Clarifications
I'm aware that putting the calling thread to sleep won't unlock the mutex, since it's still in scope, but the expected scheduling was along the lines of:
Thread1 locks, gets the mutex.
Thread2 locks, blocks.
Thread1 executes, releases the lock, and immediately attempts to lock again.
Thread2 was already waiting on the lock, gets it before thread1.
Is this expected behavior?
Yes and no. You shouldn't have any expectations about which thread will get a mutex, since it's unspecified. But it's certainly within the range of expected behavior.
Is there a way to control this behavior, such as making scoped locks behave like locking operations are queued?
Don't use mutexes this way. Just don't. Use mutexes only such that they're held for very short periods of time relative to other things a thread is doing.
If the answer to (2) is "no", is it possible to achieve something similar with Boost condition variables and not having to worry about lock/unlock calls failing?
Sure. Code what you want.
Are scoped_locks guaranteed to unlock? I'm using the RAII approach rather than manually locking/unlocking because apparently the unlock operation can fail and throw an exception, and I'm trying to make this code solid.
It's not clear what it is you're worried about, but the RAII approach is recommended.
Why are you surprised, exactly ?
If you were expecting thread 2 to acquire the mutex while thread 1 is asleep, then, yes, this is expecting behaviour and your understanding was wrong, because your lock is in scope.
But if you are surprised because of lack of alternance between thread 1 and thread 2 at the end of loop iteration, then you can have a look at this SO question about scheduling that seems "unfair"

Execution not switching between thread (c++11)

I am a beginner in C++11 multithreading. I am working with small codes and came into this problem. Here is the code:
#include <iostream>
#include <thread>
#include <vector>
#include <mutex>
std::mutex print_mutex;
void function1()
{
std::cout << "Thread1 started" << std::endl;
while (true)
{
std::unique_lock<std::mutex> lock(print_mutex);
for (size_t i = 0; i<= 1000000000; i++)
continue;
std::cout << "This is function1" << std::endl;
lock.unlock();
}
}
void function2()
{
std::cout << "Thread2 started" << std::endl;
while (true)
{
std::unique_lock<std::mutex> lock(print_mutex);
for (size_t i = 0; i <= 1000000000; i++)
continue;
std::cout << "This is function2" << std::endl;
lock.unlock();
}
}
int main()
{
std::thread t1(function1);
std::thread t2(function2);
t1.join();
t2.join();
return 0;
}
I have written code with the intuition of expecting the following output:
Thread1 started Thread2 started This is
function1 This is function2 This is function1 . . . .
But the output shown is as follows:
Thread1 started Thread2 started
This is function1 This is function1 This is
function1 . . .
Where am I going wrong?
Unlocking a mutex does not guarantee that another thread that's waiting to lock the same mutex will immediately acquire a lock.
It only guarantees that the other thread will TRY to acquire the lock.
In this case, after you unlock the mutex in one thread, the same thread will immediately try to lock it again. Even though another thread was waiting patiently, for the mutex, it's not a guarantee that the other thread will win this time. The same thread that just locked it can succeed in immediately locking it again.
Today, you're seeing that the same thread always wins the locking race. Tomorrow, you may find that it's always the other thread that does. You have no guarantees, whatsoever, which thread will acquire the mutex when there's more than one thread going after the same mutex, at the same time. The winner depends on your CPU and other hardware architecture, how busy the system is loaded, at the time, and many other factors.
Both of your thread is doing following steps:
Lock
Long empty loop
Print
Unlock
Lock
Long empty loop
(and so on)
Practically, you haven't left any time for context switching, there is a lock just right after the unlock. Solution: Swap the "lock" and the "long empty loop" steps, so only the "print" step will be locked, the scheduler can switch to the other thread during "long empty loop".
Welcome to threads!
Edit: Pro Tipp: Debugging multithreading programs is hard. But sometimes it's worth to insert a plain printf() to indicate locks and unlocks (the right order: lock, then printf and printf then unlock), even when the program seems correct. In this case you could see the zero gap between unlock-lock.
This is a valid result, your code does not try to control the execution order in any way so as long as all threads execute at some point and there's is no problem and it's a legitimate result.
This could happen even if you switched the order of the loop and the lock(see here), because again you haven't written anything that attempts to control it using e.g conditional variables or just some silly atomic_bool(it is a silly solution just to demonstrate how can you actually make it alternating and be sure it will) boolean to alternate the runs.

When should I use std::thread::detach?

Sometime I have to use std::thread to speed up my application. I also know join() waits until a thread completes. This is easy to understand, but what's the difference between calling detach() and not calling it?
I thought that without detach(), the thread's method will work using a thread independently.
Not detaching:
void Someclass::Somefunction() {
//...
std::thread t([ ] {
printf("thread called without detach");
});
//some code here
}
Calling with detaching:
void Someclass::Somefunction() {
//...
std::thread t([ ] {
printf("thread called with detach");
});
t.detach();
//some code here
}
In the destructor of std::thread, std::terminate is called if:
the thread was not joined (with t.join())
and was not detached either (with t.detach())
Thus, you should always either join or detach a thread before the flows of execution reaches the destructor.
When a program terminates (ie, main returns) the remaining detached threads executing in the background are not waited upon; instead their execution is suspended and their thread-local objects destructed.
Crucially, this means that the stack of those threads is not unwound and thus some destructors are not executed. Depending on the actions those destructors were supposed to undertake, this might be as bad a situation as if the program had crashed or had been killed. Hopefully the OS will release the locks on files, etc... but you could have corrupted shared memory, half-written files, and the like.
So, should you use join or detach ?
Use join
Unless you need to have more flexibility AND are willing to provide a synchronization mechanism to wait for the thread completion on your own, in which case you may use detach
You should call detach if you're not going to wait for the thread to complete with join but the thread instead will just keep running until it's done and then terminate without having the spawner thread waiting for it specifically; e.g.
std::thread(func).detach(); // It's done when it's done
detach basically will release the resources needed to be able to implement join.
It is a fatal error if a thread object ends its life and neither join nor detach has been called; in this case terminate is invoked.
This answer is aimed at answering question in the title, rather than explaining the difference between join and detach. So when should std::thread::detach be used?
In properly maintained C++ code std::thread::detach should not be used at all. Programmer must ensure that all the created threads gracefully exit releasing all the acquired resources and performing other necessary cleanup actions. This implies that giving up ownership of threads by invoking detach is not an option and therefore join should be used in all scenarios.
However some applications rely on old and often not well designed and supported APIs that may contain indefinitely blocking functions. Moving invocations of these functions into a dedicated thread to avoid blocking other stuff is a common practice. There is no way to make such a thread to exit gracefully so use of join will just lead to primary thread blocking. That's a situation when using detach would be a less evil alternative to, say, allocating thread object with dynamic storage duration and then purposely leaking it.
#include <LegacyApi.hpp>
#include <thread>
auto LegacyApiThreadEntry(void)
{
auto result{NastyBlockingFunction()};
// do something...
}
int main()
{
::std::thread legacy_api_thread{&LegacyApiThreadEntry};
// do something...
legacy_api_thread.detach();
return 0;
}
When you detach thread it means that you don't have to join() it before exiting main().
Thread library will actually wait for each such thread below-main, but you should not care about it.
detach() is mainly useful when you have a task that has to be done in background, but you don't care about its execution. This is usually a case for some libraries. They may silently create a background worker thread and detach it so you won't even notice it.
According to cppreference.com:
Separates the thread of execution from the thread object, allowing
execution to continue independently. Any allocated resources will be
freed once the thread exits.
After calling detach *this no longer owns any thread.
For example:
std::thread my_thread([&](){XXXX});
my_thread.detach();
Notice the local variable: my_thread, while the lifetime of my_thread is over, the destructor of std::thread will be called, and std::terminate() will be called within the destructor.
But if you use detach(), you should not use my_thread anymore, even if the lifetime of my_thread is over, nothing will happen to the new thread.
Maybe it is good idea to iterate what was mentioned in one of the answers above: When the main function is finished and main thread is closing, all spawn threads either will be terminated or suspended. So, if you are relying on detach to have a background thread continue running after the main thread is shutdown, you are in for a surprise. To see the effect try the following. If you uncomment the last sleep call, then the output file will be created and written to fine. Otherwise not:
#include <mutex>
#include <thread>
#include <iostream>
#include <fstream>
#include <array>
#include <chrono>
using Ms = std::chrono::milliseconds;
std::once_flag oflag;
std::mutex mx;
std::mutex printMx;
int globalCount{};
std::ofstream *logfile;
void do_one_time_task() {
//printMx.lock();
//std::cout<<"I am in thread with thread id: "<< std::this_thread::get_id() << std::endl;
//printMx.unlock();
std::call_once(oflag, [&]() {
// std::cout << "Called once by thread: " << std::this_thread::get_id() << std::endl;
// std::cout<<"Initialized globalCount to 3\n";
globalCount = 3;
logfile = new std::ofstream("testlog.txt");
//logfile.open("testlog.txt");
});
std::this_thread::sleep_for(Ms(100));
// some more here
for(int i=0; i<10; ++i){
mx.lock();
++globalCount;
*logfile << "thread: "<< std::this_thread::get_id() <<", globalCount = " << globalCount << std::endl;
std::this_thread::sleep_for(Ms(50));
mx.unlock();
std::this_thread::sleep_for(Ms(2));
}
std::this_thread::sleep_for(Ms(2000));
std::call_once(oflag, [&]() {
//std::cout << "Called once by thread: " << std::this_thread::get_id() << std::endl;
//std::cout << "closing logfile:\n";
logfile->close();
});
}
int main()
{
std::array<std::thread, 5> thArray;
for (int i = 0; i < 5; ++i)
thArray[i] = std::thread(do_one_time_task);
for (int i = 0; i < 5; ++i)
thArray[i].detach();
//std::this_thread::sleep_for(Ms(5000));
std::cout << "Main: globalCount = " << globalCount << std::endl;
return 0;
}

Boost shared_lock. Read preferred?

I was checking out the boost library(version 1.45) for a reader/writer lock. When I ran my tests on it, it seemed like the shared_ptr was preferring my reader threads, i.e. when my writer tried to take the lock for its operation, it didn't stop any subsequent reads from occurring.
Is it possible in boost to change this behavior?
using namespace std;
using namespace boost;
mutex outLock;
shared_mutex workerAccess;
bool shouldIWork = true;
class WorkerKiller
{
public:
void operator()()
{
upgrade_lock<shared_mutex> lock(workerAccess);
upgrade_to_unique_lock<shared_mutex> uniqueLock(lock);
cout << "Grabbed exclusive lock, killing system" << endl;
sleep(2);
shouldIWork = false;
cout << "KILLING ALL WORK" << endl;
}
private:
};
class Worker
{
public:
Worker()
{
}
void operator()()
{
shared_lock<shared_mutex> lock(workerAccess);
if (!shouldIWork) {
outLock.lock();
cout << "Workers are on strike. This worker refuses to work" << endl;
outLock.unlock();
} else {
sleep(1);
outLock.lock();
cout << "Worked finished her work" << endl;
outLock.unlock();
}
}
};
int main(int argc, char* argv[])
{
Worker w1;
Worker w2;
Worker w3;
Worker w4;
WorkerKiller wk;
boost::thread workerThread1(w1);
boost::thread workerThread2(w2);
boost::thread workerKillerThread(wk);
boost::thread workerThread3(w3);
boost::thread workerThread4(w4);
workerThread1.join();
workerThread2.join();
workerKillerThread.join();
workerThread3.join();
return 0;
}
And here is the output every time:
Worked finished her work
Worked finished her work
Worked finished her work
Worked finished her work
Grabbed exclusive lock, killing system
KILLING ALL WORK
My Requirement
If the writer tried to grab an exclusive lock, I'd like for all previous read operations to finish. And then all subsequent read operations to block.
I'm a little late to this question, but I believe I have some pertinent information.
The proposals of shared_mutex to the C++ committee, which the boost libs are based on, purposefully did not specify an API to give readers nor writers priority. This is because Alexander Terekhov proposed an algorithm about a decade ago that is completely fair. It lets the operating system decide whether the next thread to get the mutex is a reader or writer, and the operating system is completely ignorant as to whether the next thread is a reader or writer.
Because of this algorithm, the need for specifying whether a reader or writer is preferred disappears. To the best of my knowledge, the boost libs are now (boost 1.52) implemented with this fair algorithm.
The Terekhov algorithm consists of having the read/write mutex consist of two gates: gate1 and gate2. Only one thread at a time can pass through each gate. The gates can be implemented with a mutex and two condition variables.
Both readers and writers attempt to pass through gate1. In order to pass through gate1 it must be true that a writer thread is not currently inside of gate1. If there is, the thread attempting to pass through gate1 blocks.
Once a reader thread passes through gate1 it has read ownership of the mutex.
When a writer thread passes through gate1 it must also pass through gate2 before obtaining write ownership of the mutex. It can not pass through gate2 until the number of readers inside of gate1 drops to zero.
This is a fair algorithm because when there are only 0 or more readers inside of gate1, it is up to the OS as to whether the next thread to get inside of gate1 is a reader or writer. A writer becomes "prioritized" only after it has passed through gate1, and is thus next in line to obtain ownership of the mutex.
I used your example compiled against an example implementation of what eventually became shared_timed_mutex in C++14 (with minor modifications to your example). The code below calls it shared_mutex which is the name it had when it was proposed.
I got the following outputs (all with the same executable):
Sometimes:
Worked finished her work
Worked finished her work
Grabbed exclusive lock, killing system
KILLING ALL WORK
Workers are on strike. This worker refuses to work
Workers are on strike. This worker refuses to work
And sometimes:
Worked finished her work
Grabbed exclusive lock, killing system
KILLING ALL WORK
Workers are on strike. This worker refuses to work
Workers are on strike. This worker refuses to work
Workers are on strike. This worker refuses to work
And sometimes:
Worked finished her work
Worked finished her work
Worked finished her work
Worked finished her work
Grabbed exclusive lock, killing system
KILLING ALL WORK
I believe it should be theoretically possible to also obtain other outputs, though I did not confirm that experimentally.
In the interest of full disclosure, here is the exact code I executed:
#include "../mutexes/shared_mutex"
#include <thread>
#include <chrono>
#include <iostream>
using namespace std;
using namespace ting;
mutex outLock;
shared_mutex workerAccess;
bool shouldIWork = true;
class WorkerKiller
{
public:
void operator()()
{
unique_lock<shared_mutex> lock(workerAccess);
cout << "Grabbed exclusive lock, killing system" << endl;
this_thread::sleep_for(chrono::seconds(2));
shouldIWork = false;
cout << "KILLING ALL WORK" << endl;
}
private:
};
class Worker
{
public:
Worker()
{
}
void operator()()
{
shared_lock<shared_mutex> lock(workerAccess);
if (!shouldIWork) {
lock_guard<mutex> _(outLock);
cout << "Workers are on strike. This worker refuses to work" << endl;
} else {
this_thread::sleep_for(chrono::seconds(1));
lock_guard<mutex> _(outLock);
cout << "Worked finished her work" << endl;
}
}
};
int main()
{
Worker w1;
Worker w2;
Worker w3;
Worker w4;
WorkerKiller wk;
thread workerThread1(w1);
thread workerThread2(w2);
thread workerKillerThread(wk);
thread workerThread3(w3);
thread workerThread4(w4);
workerThread1.join();
workerThread2.join();
workerKillerThread.join();
workerThread3.join();
workerThread4.join();
return 0;
}
A google search of "boost shared lock starvation" turned up this link:
Example for boost shared_mutex (multiple reads/one write)?
It looks like "upgrade" might be the key. See also:
Example of how to use boost upgradeable mutexes
http://HowardHinnant.github.io/shared_mutex