Mutex locking and unlocking time difference - c++

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.

Related

C++ What possible ways can a detached thread signal it is terminating?

I had three initial ideas about this
Firstly some kind of counter? (Maybe using mutex?)
Some kind of semophore? (I don't know much about these) OR perhaps a promise/future combination
Some other kind of signal/slot mechanism, similar to that of the signal created by CTRL-C (SIGINT etc)
I'm working on some software which makes use of detached threads to do some work. Unfortunatly the threads don't clean up nicely, they just quit at the end of execution. This is fine for communication in one direction (ie; main() can quit first), but won't work the other way around - at the moment there is no way for main() to know when the threads have finished working and to exit gracefully.
To expand on those bullet points...
My initial idea was to have a protected region of variables - could be a counter or an array of flags, one for each thread, and to access these using a mutex. The mutex might not even be necessary if using one variable per detached thread to signal the end of the thread working, because main() will "poll" these variables, which is a read-only operation. Only the detached threads themselves need write access. If more than one detached thread uses the same counter/variable then a mutex would be required.
The next idea I had was to use a semophore (which is something I really know nothing about) or promise/future combinations, which I think would work as a possible option.
The final thought was some kind of signals mechanism, like possibly "stealing" a SIGxyz signal (like SIGINT) and using that to some how communicate the end of a thread execution. I'm not confident about this one however.
My question is really - how is this supposed to be done? What would the typical engineering solution to this problem be?
(Final thought: Using a file, or a pipe? Seems a bit complicated though?)
Perhaps I overlooked the question but I think you could use an atomic variable as a flag in order to notify the detached thread's termination.
Something like the following example:
#include <thread>
#include <iostream>
#include <atomic>
int main()
{
// Define a flag to notify detached thread's termination
std::atomic_bool term_flag;
// Define some function to run concurrently
auto func = [&term_flag](){
std::this_thread::sleep_for(std::chrono::seconds(2));
term_flag = true;
};
// Run and detach the thread
term_flag = false;
std::thread t(func);
t.detach();
// Wait until detached thread termination
while(!term_flag)
std::this_thread::yield();
std::cout << "Detached Thread has terminated properly" << std::endl;
return 0;
}
Output:
Detached Thread has terminated properly
EDIT:
As Hans Passant mentioned, you could also use a condition variable associated with a mutex to do it.
This would be a better solution (but a bit less readable in my humble opinion) since we have more control over how much to wait.
The basic example above could then be rewritten as:
#include <thread>
#include <iostream>
#include <mutex>
#include <condition_variable>
int main()
{
// Define the mutex and the condition variable to notify the detached thread's termination
std::mutex m;
std::condition_variable cv;
// Define some function to run concurrently
auto func = [&cv](){
std::this_thread::sleep_for(std::chrono::seconds(2));
cv.notify_one();
};
// Run and detach the thread
std::thread t(func);
t.detach();
// Wait until detached thread termination
{
std::unique_lock<std::mutex> lk(m);
cv.wait(lk);
}
std::cout << "Detached Thread has terminated properly" << std::endl;
return 0;
}

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.

What does std::thread.join() do?

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().

Using boost::lock_guard for simple shared data locking

I am a newcomer to the Boost library, and am trying to implement a simple producer and consumer threads that operate on a shared queue. My example implementation looks like this:
#include <iostream>
#include <deque>
#include <boost/thread.hpp>
boost::mutex mutex;
std::deque<std::string> queue;
void producer()
{
while (true) {
boost::lock_guard<boost::mutex> lock(mutex);
std::cout << "producer() pushing string onto queue" << std::endl;
queue.push_back(std::string("test"));
}
}
void consumer()
{
while (true) {
boost::lock_guard<boost::mutex> lock(mutex);
if (!queue.empty()) {
std::cout << "consumer() popped string " << queue.front() << " from queue" << std::endl;
queue.pop_front();
}
}
}
int main()
{
boost::thread producer_thread(producer);
boost::thread consumer_thread(consumer);
sleep(5);
producer_thread.detach();
consumer_thread.detach();
return 0;
}
This code runs as I expect, but when main exits, I get
/usr/include/boost/thread/pthread/mutex.hpp:45:
boost::mutex::~mutex(): Assertion `!pthread_mutex_destroy(&m)' failed.
consumer() popped string test from queue
Aborted
(I'm not sure if the output from consumer is relevant in that position, but I've left it in.)
Am I doing something wrong in my usage of Boost?
A bit off-topic but relevant imo (...waits for flames in comments).
The consumer model here is very greedy, looping and checking for data on the queue continually. It will be more efficient (waste less CPU cycles) if you have your consumer threads awakened determistically when data is available, using inter-thread signalling rather than this lock-and-peek loop. Think about it this way: while the queue is empty, this is essentially a tight loop only broken by the need to acquire the lock. Not ideal?
void consumer()
{
while (true) {
boost::lock_guard<boost::mutex> lock(mutex);
if (!queue.empty()) {
std::cout << "consumer() popped string " << queue.front() << " from queue" << std::endl;
queue.pop_front();
}
}
}
I understand that you are learning but I would not advise use of this in 'real' code. For learning the library though, it's fine. To your credit, this is a more complex example than necessary to understand how to use the lock_guard, so you are aiming high!
Eventually you will most likely build (or better if available, reuse) code for a queue that signals workers when they are required to do work, and you will then use the lock_guard inside your worker threads to mediate accesses to shared data.
You give your threads (producer & consumer) the mutex object and then detach them. They are supposed to run forever. Then you exit from your program and the mutex object is no longer valid. Nevertheless your threads still try to use it, they don't know that it is no longer valid. If you had used the NDEBUG define you would have got a coredump.
Are you trying to write a daemon application and this is the reason for detaching threads?
When main exits, all the global objects are destroyed. Your threads, however, do continue to run. You therefore end up with problems because the threads are accessing a deleted object.
Bottom line is that you must terminate the threads before exiting. The only what to do this though is to get the main program to wait (by using a boost::thread::join) until the threads have finished running. You may want to provide some way of signaling the threads to finish running to save from waiting too long.
The other issue is that your consumer thread continues to run even when there is not data. You might want to wait on a boost::condition_variable until signaled that there is new data.