I was reading through a Boost Mutex tutorial on drdobbs.com, and found this piece of code:
#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/bind.hpp>
#include <iostream>
boost::mutex io_mutex;
void count(int id)
{
for (int i = 0; i < 10; ++i)
{
boost::mutex::scoped_lock
lock(io_mutex);
std::cout << id << ": " <<
i << std::endl;
}
}
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;
}
Now I understand the point of a Mutex is to prevent two threads from accessing the same resource at the same time, but I don't see the correlation between io_mutex and std::cout. Does this code just lock everything within the scope until the scope is finished?
Now I understand the point of a Mutex is to prevent two threads from accessing the same resource at the same time, but I don't see the correlation between io_mutex and std::cout.
std::cout is a global object, so you can see that as a shared resource. If you access it concurrently from several threads, those accesses must be synchronized somehow, to avoid data races and undefined behavior.
Perhaps it will be easier for you to notice that concurrent access occurs by considering that:
std::cout << x
Is actually equivalent to:
::operator << (std::cout, x)
Which means you are calling a function that operates on the std::cout object, and you are doing so from different threads at the same time. std::cout must be protected somehow. But that's not the only reason why the scoped_lock is there (keep reading).
Does this code just lock everything within the scope until the scope is finished?
Yes, it locks io_mutex until the lock object itself goes out of scope (being a typical RAII wrapper), which happens at the end of each iteration of your for loop.
Why is it needed? Well, although in C++11 individual insertions into cout are guaranteed to be thread-safe, subsequent, separate insertions may be interleaved when several threads are outputting something.
Keep in mind that each insertion through operator << is a separate function call, as if you were doing:
std::cout << id;
std::cout << ": ";
std::cout << i;
std::cout << endl;
The fact that operator << returns the stream object allows you to chain the above function calls in a single expression (as you have done in your program), but the fact that you are having several separate function calls still holds.
Now looking at the above snippet, it is more evident that the purpose of this scoped lock is to make sure that each message of the form:
<id> ": " <index> <endl>
Gets printed without its parts being interleaved with parts from other messages.
Also, in C++03 (where insertions into cout are not guaranteed to be thread-safe) , the lock will protect the cout object itself from being accessed concurrently.
A mutex has nothing to do with anything else in the program
(except a conditional variable), at least at a higher level.
A mutex has two effeccts: it controls program flow, and prevents
multiple threads from executing the same block of code
simultaneously. It also ensures memory synchronization. The
important issue here, is that mutexes aren't associated with
resources, and don't prevent two threads from accessing the same
resource at the same time. A mutex defines a critical section
of code, which can only be entered by one thread at a time. If
all of the use of a particular resource is done in critical
sections controled by the same mutex, then the resource is
effectively protected by the mutex. But the relationship is
established by the coder, by ensuring that all use does take
place in the critical sections.
Related
In a C++ class, How can I limit the number calls/uses of a certain function for each thread?
For example, each thread is allowed only to use a certain data setter for 3 times.
You just have to count how often the method has been called for each thread and then react accordingly:
void Foo::set(int x) {
static std::map<std::thread::id,unsigned> counter;
auto counts = ++counter[std::this_thread::get_id()];
if (counts > max_counts) return;
x_member = x;
}
This is just to outline the basic idea. I am not so sure about the static map. I am not even sure if it is a good idea to let the method itself implement the counter. I would rather put this elsewhere, eg each thread could get a CountedFoo instance that holds a reference to the actual Foo object and the CountedFoo controls the maximum number of calls.
PS: And of course, don't forget to use some synchronisation when multiple threads are calling the method concurrently (for the sake of brevity I did not include any mutex or similar in the above code).
Using std::map to store thread Ids as sugested by #formerlyknownas_463035818 would probably be the most robust solution, but synchronization might prove more complex.
The fastest solution to this issue is using thread_local. This will enable each thread to have its own copy of the counter. Here is the working example which might prove useful.
thread_local unsigned int N_Calls = 0;
std::mutex mtx;
void controlledIncreese(const std::string& thread_name){
while (N_Calls < 3) {
++N_Calls;
std::this_thread::sleep_for(std::chrono::seconds(rand() % 2));
std::lock_guard<std::mutex> lock(mtx);
std::cout << "Call for thread " << thread_name.c_str() << ": " << N_Calls << '\n';
}
}
int main(){
std::thread first_t(controlledIncreese, "first"), second_t(controlledIncreese, "second");
first_t.join();
second_t.join();
}
Since both Threads are using std::cout the actual output will be sequential, so this specific example is not very useful but it does provide easy working solution to thread execution counting problem.
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"
boost::timed_lock
void wait(int seconds)
{
boost::this_thread::sleep(boost::posix_time::seconds(seconds));
}
boost::timed_mutex mutex;
void thread()
{
for (int i = 0; i < 5; ++i)
{
wait(1);
boost::unique_lock<boost::timed_mutex> lock(mutex, boost::try_to_lock);
if (!lock.owns_lock())
lock.timed_lock(boost::get_system_time() + boost::posix_time::seconds(1));//<<<<
std::cout << "Thread " << boost::this_thread::get_id() << ": " << i << std::endl;
boost::timed_mutex *m = lock.release();
m->unlock();
}
}
timed_lock
Question> I have problems to understand the following lines:
if (!lock.owns_lock())
lock.timed_lock(boost::get_system_time() +
boost::posix_time::seconds(1));//<<<<
Here is my understanding. Assume lock.owns_lock() returns false which means the current object DOES NOT own the lock on the lockable object. So next line will be executed. If after the specified time lapsed and the object still cannot get the lock, then the boost::timed_lock will return false. So the following line will be executed???
std::cout << "Thread " << boost::this_thread::get_id() << ": " << i << std::endl;
Is this idea correct? I think the purpose of the code is to make sure the above line is executed iff the object has the lock. But based on my understanding(i guess is NOT correct), the above line always gets run!
Where is the problem?
You are right and the example does NOT guarantee the lock is always properly acquired before executing the protected code.
Given the explanation below the example:
The above program passes boost::try_to_lock as the second parameter to the constructor of boost::unique_lock. Whether or not the mutex has been acquired can be checked via the owns_lock() method afterwards. In case it has not - owns_lock() returns false - another function provided by boost::unique_lock is used: timed_lock() waits for a certain time to acquire the mutex. The given program waits for up to one second which should be more than enough time to acquire the mutex.
The example actually shows the three fundamental ways of acquiring a mutex: lock() waits until the mutex has been acquired. try_lock() does not wait but acquires the mutex if it is available at the time of the call and returns false otherwise. Finally, timed_lock() tries to acquire the mutex within a given period of time. As with try_lock(), success or failure is indicated by the return value of type bool.
the authors seem aware of the problem (given that the document the return value of timed_lock) but did not think a re-test if the lock had been acquired was needed (as demonstrated by them saying "waits for up to one second which should be more than enough time to acquire the mutex").
One error in your understanding:
If after the specified time lapsed and the object still cannot get the lock, then the boost::timed_lock will return false.
This is not true. timed_lock will 'continuously' try to obtain the lock, but give up if the specified time has expired.
You are right. The example doesn't properly handle the state of when the mutex fails to lock. If you read closely just below that example you'll see this quoted there:
The above example uses various methods to illustrate some of the features provided by boost::unique_lock. Certainly, the usage of these features does not necessarily make sense for the given scenario; the usage of boost::lock_guard in the previous example was already adequate. This example is rather meant to demonstrate the possibilities offered by boost::unique_lock.
I have a set of C++ functions:
funcB(){};
funcC(){};
funcA()
{
funcB();
funcC();
}
Now I want to make funcA atomic, ie funcB and funcC calls inside funcA should be executed atomically. Is there any way to achieve this?
One way you can accomplish this is to use the new (C++11) features std::mutex and std::lock_guard.
For each protected resource, you instantiate a single global std::mutex; each thread then locks that mutex, as it requires, by the creation of a std::lock_guard:
#include <thread>
#include <iostream>
#include <mutex>
#include <vector>
// A single mutex, shared by all threads. It is initialized
// into the "unlocked" state
std::mutex m;
void funcB() {
std::cout << "Hello ";
}
void funcC() {
std::cout << "World." << std::endl;
}
void funcA(int i) {
// The creation of lock_guard locks the mutex
// for the lifetime of the lock_guard
std::lock_guard<std::mutex> l(m);
// Now only a single thread can run this code
std::cout << i << ": ";
funcB();
funcC();
// As we exit this scope, the lock_guard is destroyed,
// the mutex is unlocked, and another thread is allowed to run
}
int main () {
std::vector<std::thread> vt;
// Create and launch a bunch of threads
for(int i =0; i < 10; i++)
vt.push_back(std::thread(funcA, i));
// Wait for all of them to complete
for(auto& t : vt)
t.join();
}
Notes:
In your example some code unrelated to funcA could invoke either funcB or funcC without honoring the lock that funcA set.
Depending upon how your program is structured, you may want to manage the lifetime of the mutex differently. As an example, it might want to be a class member of the class that includes funcA.
In general, NO. Atomic operations are very precisely defined. What you want is a semaphore or a mutex.
If you are using GCC 4.7 than you can use the new Transactional Memory feature to do the following:
Transactional memory is intended to make programming with threads simpler, in particular synchronizing access to data shared between several threads using transactions. As with databases, a transaction is a unit of work that either completes in its entirety or has no effect at all (i.e., transactions execute atomically). Further, transactions are isolated from each other such that each transaction sees a consistent view of memory.
Currently, transactions are only supported in C++ and C in the form of transaction statements, transaction expressions, and function transactions. In the following example, both a and b will be read and the difference will be written to c, all atomically and isolated from other transactions:
__transaction_atomic { c = a - b; }
Therefore, another thread can use the following code to concurrently update b without ever causing c to hold a negative value (and without having to use other synchronization constructs such as locks or C++11 atomics):
__transaction_atomic { if (a > b) b++; }
The precise semantics of transactions are defined in terms of the C++11/C1X memory model (see below for a link to the specification). Roughly, transactions provide synchronization guarantees that are similar to what would be guaranteed when using a single global lock as a guard for all transactions. Note that like other synchronization constructs in C/C++, transactions rely on a data-race-free program (e.g., a nontransactional write that is concurrent with a transactional read to the same memory location is a data race).
More info: http://gcc.gnu.org/wiki/TransactionalMemory
I have a test program that I wrote to try and debug a GMutex issue that I am having and I cannot seem to figure it out. I am using the class below to lock and unlock a mutex within a scoped context. This is similar to BOOST's guard.
/// #brief Helper class used to create a mutex.
///
/// This helper Mutex class will lock a mutex upon creation and unlock when deleted.
/// This class may also be referred to as a guard.
///
/// Therefore this class allows scoped access to the Mutex's locking and unlocking operations
/// and is good practice since it ensures that a Mutex is unlocked, even if an exception is thrown.
///
class cSessionMutex
{
GMutex* apMutex;
/// The object used for logging.
mutable cLog aLog;
public:
cSessionMutex (GMutex *ipMutex) : apMutex(ipMutex), aLog ("LOG", "->")
{
g_mutex_lock(apMutex);
aLog << cLog::msDebug << "MUTEX LOCK " << apMutex << "," << this << cLog::msEndL;
}
~cSessionMutex ()
{
aLog << cLog::msDebug << "MUTEX UNLOCK " << apMutex << "," << this << cLog::msEndL;
g_mutex_unlock(apMutex);
}
};
Using this class, I call it as follows:
bool van::cSessionManager::RegisterSession(const std::string &iSessionId)
{
cSessionMutex lRegistryLock (apRegistryLock);
// SOME CODE
}
where apRegistryLock is a member variable of type GMutex* and is initialized using g_mutex_new() before I ever call RegisterSession.
With this said, when I run the application with several threads, I sometimes notice at the beginning, when RegisterSession is called for the first few times that the log (from the constructor above)
[DEBUG] LOG.-> - MUTEX LOCK 0x26abb40,0x7fc14ad7ae10
[DEBUG] LOG.-> - MUTEX LOCK 0x26abb40,0x7fc14af7ce10
is logged twice in a row with the same mutex but different instance; therefore, suggesting that the mutex is being locked twice or the second lock is simply being ignored - which is seriously bad.
Moreover, it is worth noting that I also check to see if these logs were initiated from the same thread using the g_thread_self() function, and this returned two separate thread identifiers; thus, suggesting that the mutex was locked twice from separate threads.
So my question is, how is it possible for this to occur?
If it's called twice in the same call chain in the same thread this could happen. The second lock is typically (although not always) ignored. At least in pthreads it's possible to configure multiple locks as counted.
What was happening in my case was there was another thread that was calling g_cond_timed_wait function with the same mutex, but with the mutex unlocked. In this case, g_cond_timed_wait function unlocks a mutex that is not locked and leaves the mutex in an undefined state, which explains why I was seeing the behaviour explained in this question: the mutex being locked twice.