I am trying to use the advise found here: How to assert if a std::mutex is locked? to check if a mutex is currently locked. It seems to work at a first glance but it crashed when you try to use it from multiple threads. My guess is that unique_lock is not thread safe which would make a lot of sense which would mean there is no easy way to check if a mutex is already locked without writing a wrapper.
#include <iostream>
#include <thread>
#include <mutex>
long glob=0;
std::mutex mutex_;
std::unique_lock <std::mutex> glock (mutex_, std::defer_lock);
void call_from_thread (int tid)
{
std::cout <<"Started "<<tid<<std::endl;
for (int i=0; i<1000; ++i)
{
std::lock_guard< std::unique_lock <std::mutex> > lock2 (glock);
std::cout<<tid<<":"<<i<<":"<<glob<<std::endl;
++glob;
};
std::cout<<"Done "<<tid<<std::endl;
};
int main ()
{
std::thread t [10];
for (int i=0; i<10; ++i)
{
t[i]=std::thread (call_from_thread, i);
};
for (int i=0; i<10; ++i)
{
t[i].join ();
};
std::cout <<"Glob = "<<glob<<std::endl;
return 0;
}
Related
i tried to profile performance of my code, and thats what i get:
i took a code from microsoft docs from topic about profiling:
#include <iostream>
#include <limits>
#include <mutex>
#include <random>
#include <functional>
//.cpp file code:
static constexpr int MIN_ITERATIONS = std::numeric_limits<int>::max() / 1000;
static constexpr int MAX_ITERATIONS = MIN_ITERATIONS + 10000;
long long m_totalIterations = 0;
std::mutex m_totalItersLock;
int getNumber()
{
std::uniform_int_distribution<int> num_distribution(MIN_ITERATIONS, MAX_ITERATIONS);
std::mt19937 random_number_engine; // pseudorandom number generator
auto get_num = std::bind(num_distribution, random_number_engine);
int random_num = get_num();
auto result = 0;
{
std::lock_guard<std::mutex> lock(m_totalItersLock);
m_totalIterations += random_num;
}
// we're just spinning here
// to increase CPU usage
for (int i = 0; i < random_num; i++)
{
result = get_num();
}
return result;
}
void doWork()
{
std::wcout << L"The doWork function is running on another thread." << std::endl;
auto x = getNumber();
}
int main()
{
std::vector<std::thread> threads;
for (int i = 0; i < 10; ++i) {
threads.push_back(std::thread(doWork));
std::cout << "The Main() thread calls this after starting the new thread" << std::endl;
}
for (auto& thread : threads) {
thread.join();
}
return 0;
}
, and still i'm getting different output (or no output actually). Can someone help me pls? I'm trying to do that on Visual Studio Community 2019
This is an exercise of using atomic_flag with acquire/release memory model to implement a very simple mutex.
There are THREADS number of threads, and each thread increment cou LOOP number of times. The threads are synchronized with this simple mutex. However, the code throws exception in thread.join() function. Could someone please enlighten me why this does not work? Thank you in advance!
#include <atomic>
#include <thread>
#include <assert.h>
#include <vector>
using namespace std;
class mutex_simplified {
private:
atomic_flag flag;
public:
void lock() {
while (flag.test_and_set(memory_order_acquire));
}
void unlock() {
flag.clear(memory_order_release);
}
};
mutex_simplified m_s;
int cou(0);
const int LOOP = 10000;
const int THREADS = 1000;
void increment() {
for (unsigned i = 0; i < LOOP; i++) {
m_s.lock();
cou++;
m_s.unlock();
}
}
int main() {
thread a(increment);
thread b(increment);
vector<thread> threads;
for (int i = 0; i < THREADS; i++)
threads.push_back(thread(increment));
for (auto & t : threads) {
t.join();
}
assert(cou == THREADS*LOOP);
}
You are not joining threads a and b. As the result, they might be still running while your program is finishing its execution.
You should either add a.join() and b.join() somewhere, or probably just remove them as the assertion in your main function will fail if you keep them.
Another issue is that you need to explicitly initialize atomic_flag instance in your mutex constructor. It might not cause issues in your example because global variables are zero-initialized, but this might cause issues later.
I have this C++ class with static mutex as private member of the class to protect cout in another public function of the class. But when I call object of the class from two threads I get a racing condition. Not sure why ?
class ThreadSafePrint
{
public:
void myprint(int threadNumber)
{
std::lock_guard<std::mutex> gaurd(mymutex);
cout <<"Thread " << threadNumber << endl;
}
private:
static std::mutex mymutex;
};
std::mutex ThreadSafePrint::mymutex;
int main()
{
ThreadSafePrint obj;
std::vector<std::thread> workers;
int threadNumber;
// create 2 threads and pass a number
for(int i=0; i<2;++i)
{
// threadNumber = 0 for 1st thread
if(i==0)
{
threadNumber = i;
}
// threadNumber = 1 for 2nd thread
if(i==1)
{
threadNumber = i;
}
workers.push_back(std::thread([&obj,&threadNumber]()
{
obj.myprint(threadNumber);
}));
}
// join all threads
std::for_each(workers.begin(), workers.end(),[](std::thread & th)
{
th.join();
});
return 0;
}
Here are some results:
>> ./mythreads
Thread 1
Thread 1
>> ./mythreads
Thread 0
Thread 0
You capture a reference to the local variable threadNumber in two worker threads, access it in both threads, and mutate it in the main thread without any synchronisation. This is indeed a race condition. Capture by value instead.
workers.push_back(std::thread([&obj, threadNumber]()
You have to capture threadNumber by value, not by reference.
Exchange:
workers.push_back(std::thread([&obj,&threadNumber]()
by
workers.push_back(std::thread([&obj,threadNumber]()
Otherwise the variable threadNumber will be altered also for the first thread, by the second loop run.
#include <iostream>
#include <thread>
#include <mutex>
#include <vector>
#include <algorithm>
class ThreadSafePrint
{
public:
void myprint(int threadNumber)
{
std::lock_guard<std::mutex> gaurd(mymutex);
std::cout <<"Thread " << threadNumber << std::endl;
}
private:
static std::mutex mymutex;
};
std::mutex ThreadSafePrint::mymutex;
int main()
{
ThreadSafePrint obj;
std::vector<std::thread> workers;
int threadNumber;
// create 2 threads and pass a number
for(int i=0; i<2;++i)
{
// threadNumber = 0 for 1st thread
if(i==0)
{
threadNumber = i;
}
// threadNumber = 1 for 2nd thread
if(i==1)
{
threadNumber = i;
}
workers.push_back(std::thread([&obj,threadNumber]()
{
obj.myprint(threadNumber);
}));
}
// join all threads
std::for_each(workers.begin(), workers.end(),[](std::thread & th)
{
th.join();
});
return 0;
}
When you create your threads, you explicitly ask the compiler to provide the thread with access to the same instance of the variable threadNumber that the main function/thread is using.
[&threadNumber]
Again: this is an explicit share.
Indeed, your code suggests that you might want to better grasp the language before you experiment with threading, this code is very strange:
int threadNumber;
// create 2 threads and pass a number
for(int i=0; i<2;++i)
{
// threadNumber = 0 for 1st thread
if(i==0)
{
threadNumber = i;
}
// threadNumber = 1 for 2nd thread
if(i==1)
{
threadNumber = i;
}
It's unclear why anyone would write this instead of:
for (int i = 0; i < 2; ++i) {
workers.push_back(std::thread([&obj, i] () {
obj.myprint(threadNumber);
}));
}
Even this still has a number of design oddities - why are you passing obj by reference? It's an empty class with one static member, you could just as easily avoid the capture and write:
for (int i = 0; i < 2; ++i) {
workers.emplace_back([] (int threadNumber) {
ThreadSafePrint obj;
obj.myprint(threadNumber);
}, i); // pass `i` -> `threadNumber`
}
Looking at the following example,
#include <atomic>
extern std::atomic<int> TheVal;
extern std::atomic<bool> Ready;
int Unrelated;
void test() {
for (int i=0; i<100; ++i) {
Unrelated = 42; // A loop-invariant store
if (Ready.load(std::memory_order_acquire)) continue;
TheVal.store(i, std::memory_order_release);
Ready.store(1, std::memory_order_release);
}
}
Is the compiler allowed to move the store to 'Unrelated' out of the loop such that test() would be similar to the following?
void test() {
Unrelated = 42; // Move the loop-invariant store here
for (int i=0; i<100; ++i) {
if (Ready.load(std::memory_order_acquire)) continue;
TheVal.store(i, std::memory_order_release);
Ready.store(1, std::memory_order_release);
}
}
If the variables 'Ready' and 'TheVal' were not atomic then this optimization would be surely safe, but does their atomicity prevent this optimization?
I expect to get numbers from 0 to 4 in random order, but instead, I have some unsynchronized mess
What i do wrong?
#include <iostream>
#include <windows.h>
#include <process.h>
using namespace std;
void addQuery(void *v );
HANDLE ghMutex;
int main()
{
HANDLE hs[5];
ghMutex = CreateMutex( NULL, FALSE, NULL);
for(int i=0; i<5; ++i)
{
hs[i] = (HANDLE)_beginthread(addQuery, 0, (void *)&i);
if (hs[i] == NULL)
{
printf("error\n"); return -1;
}
}
printf("WaitForMultipleObjects return: %d error: %d\n",
(DWORD)WaitForMultipleObjects(5, hs, TRUE, INFINITE), GetLastError());
return 0;
}
void addQuery(void *v )
{
int t = *((int*)v);
WaitForSingleObject(ghMutex, INFINITE);
cout << t << endl;
ReleaseMutex(ghMutex);
_endthread();
}
You have to read and write the shared variable inside the lock. You are reading it outside of the lock and thus rendering the lock irrelevant.
But even that's not enough since your shared variable is a loop variable that you are writing to without protection of the lock. A much better example would run like this:
#include <iostream>
#include <windows.h>
#include <process.h>
using namespace std;
void addQuery(void *v );
HANDLE ghMutex;
int counter = 0;
int main()
{
HANDLE hs[5];
ghMutex = CreateMutex( NULL, FALSE, NULL);
for(int i=0; i<5; ++i)
{
hs[i] = (HANDLE)_beginthread(addQuery, 0, NULL);
if (hs[i] == NULL)
{
printf("error\n"); return -1;
}
}
printf("WaitForMultipleObjects return: %d error: %d\n",
(DWORD)WaitForMultipleObjects(5, hs, TRUE, INFINITE), GetLastError());
return 0;
}
void addQuery(void *v)
{
WaitForSingleObject(ghMutex, INFINITE);
cout << counter << endl;
counter++;
ReleaseMutex(ghMutex);
_endthread();
}
If you can, use a critical section rather than a mutex because they are simpler to use and more efficient. But they have the same semantics in that they only protect code inside the locking block.
Note: Jerry has pointer out some other problems, but I've concentrated on the high level trheading and serialization concerns.
Your synchronization has some issues as you want to get numbers from 0 to 4 in random order.
The problem is that the variable i is write outside the lock and every time the addQuery method get called by the execution of a thread, it get the modified version of variable i. That why you may see 5 as the value at the output for all.
So, here is my fix for this scenario. Instead of pass the address of variable i in parameters of the function addQuery, you should pass it's value. Hope it helps:
#include <iostream>
#include <windows.h>
#include <process.h>
using namespace std;
void addQuery(void *v);
HANDLE ghMutex;
int main()
{
HANDLE hs[5];
ghMutex = CreateMutex(NULL, FALSE, NULL);
for (int i = 0; i<5; ++i)
{
hs[i] = (HANDLE)_beginthread(addQuery, 0, (void *)i);
if (hs[i] == NULL)
{
printf("error\n"); return -1;
}
}
printf("WaitForMultipleObjects return: %d error: %d\n",
(DWORD)WaitForMultipleObjects(5, hs, TRUE, INFINITE), GetLastError());
return 0;
}
void addQuery(void *v)
{
int t = (int)v;
WaitForSingleObject(ghMutex, INFINITE);
cout << t << endl;
ReleaseMutex(ghMutex);
_endthread();
}