Reputation: 753
I have tried the mutex::try_lock() member in a program, which does the following:
1) It deliberately locks a mutex in a parallel thread.
2) In the main thread, it tries to lock the mutex using try_lock().
a) If the lock isn't acquired, it adds chars to a string.
b) When the lock is acquired, it prints the string.
I have tested this program on 2 online compilers:
1) On coliru, (which has a thread::hardware_concurrency() of 1), the program is here:
int main()
{
/// Lock the mutex for 1 nanosecond.
thread t {lock_mutex};
job();
t.join();
}
/// Lock the mutex for 1 nanosecond.
void lock_mutex()
{
m.lock();
this_thread::sleep_for(nanoseconds {1});
m.unlock();
}
void job()
{
cout << "starting job ..." << endl;
int lock_attempts {};
/// Try to lock the mutex.
while (!m.try_lock())
{
++lock_attempts;
/// Lock not acquired.
/// Append characters to the string.
append();
}
/// Unlock the mutex.
m.unlock();
cout << "lock attempts = " << lock_attempts
<< endl;
/// Lock acquired.
/// Print the string.
print();
}
/// Append characters to the string
void append()
{
static int count = 0;
s.push_back('a');
/// For every 5 characters appended,
/// append a space.
if (++count == 5)
{
count = 0;
s.push_back(' ');
}
}
/// Print the string.
void print()
{
cout << s << endl;
}
Here, the program output is as expected:
starting job ...
lock attempts = 2444
aaaaa aaaaa aaaaa ...
However, here, if I remove the following statement from the program:
cout << "starting job ..." << endl;
the output shows:
lock attempts = 0
Why does this happen?
2) On the other hand when I try this program (even locking for 1 second rather than 1 nanosecond) on ideone - here - I always get an output showing:
lock attempts = 0
This happens even if the diagnostic "starting job" is present in the program.
ideone has a thread::hardware_concurrency() of 8.
In other words, I successfully get the lock immediately. Why does this happen?
Note that this is NOT a case of try_lock() spuriously failing. In that case, though there is no existing lock on the mutex, the member returns false, indicating an unsuccessful locking attempt.
Here, the OPPOSITE appears to be happening. Though a lock (apparently) exists on the mutex, the member returns true, indicating a new lock has been successfully taken! Why?
Upvotes: 0
Views: 130
Reputation: 561
calling cout.operator << (...) with std::endl calls flush. This is a switch into kernel and gives a lot of time (some nano seconds :) ) to allow the lock_mutex thread to run. When you are not calling this function the lock_mutex has not started yet. Due to the call of into kernel you might even see this in a single core system.
Upvotes: 2