Say I have something like this:
#include <iostream>
#include <Poco/Mutex.h>
Poco::FastMutex mutex;
int main()
{
for(int i = 0; i < 10; ++i)
{
Poco::FastMutex::ScopedLock lock(mutex);
// do some stuff...
}
return 0;
};
Will the mutex be acquired on every iteration or only once? If I want to protect the whole loop, would it be better to move it outside, like this?
{
Poco::FastMutex::ScopedLock lock(mutex);
for(int i = 0; i < 10; ++i)
{
// do some stuff...
}
return 0;
}
The mutex will be acquired at each iteration.
So yes, you have to move the lock outside the loop to protect the whole loop.
Related
I'm working on a college assignment and have been tasked with showing a basic mutex lock example. I've never worked with threads in any form, so I'm a total beginner working with POSIX threads in C++.
What I'm trying to get the program to do is create 1000 threads that increment a global integer by 1000.
#include <iostream>
#include <stdlib.h>
#include <pthread.h>
#include <sys/types.h>
#include <unistd.h>
#include <thread>
pthread_t threadArr[1000];
pthread_mutex_t lock;
// Global int to increment
int numberToInc = 0;
void* incByTwo(void*)
{
pthread_mutex_lock(&lock);
for(int j = 0; j < 1000; j++){
numberToInc += 1;
}
pthread_mutex_unlock(&lock);
return NULL;
}
int main()
{
//Creates 1000 threads with incByTwo func
for(int i = 0; i < 1000; i++){
pthread_create(&threadArr[i], NULL, incByTwo, NULL);
}
std::cout << "\n" << numberToInc << "\n";
return 0;
}
The following produces a series of different results, obviously because the threads are executing concurrently, right?
Now, I've gotten it to work correctly by inserting
for(int i = 0; i < 1000; i++){
pthread_join(threadArr[i], NULL);
}
After the thread creation loop, but then removing the mutex locks, it still works. I've been trying to piece out how pthread_join works but I'm a little lost. Any advice?
Sorted a way to show the mutex lock in action. So when I output the global var in the function, without mutex locks it has the potential to show the results out of order.
Running the number range with mutex locks, out looks like:
1000
2000
3000
... (etc)
10000
With mutex locks removed, the output can vary in the order.
E.g.
1000
2000
4000
6000
3000
5000
7000
8000
9000
10000
While the final result of the three threads is correct, the sequence is out of order. In the context of this program it doesn't really matter but I'd imagine if it's passing inconsistently sequenced values it messes things up?
pthread_t threadArr[10];
pthread_mutex_t lock;
int numberToInc = 0;
void* incByTwo(void*)
{
pthread_mutex_lock(&lock);
for(int j = 0; j < 1000; j++){
numberToInc += 1;
}
std::cout << numberToInc << "\n";
pthread_mutex_unlock(&lock);
return NULL;
}
int main()
{
if (pthread_mutex_init(&lock, NULL) != 0)
{
printf("\n mutex init failed\n");
return 1;
}
for(int i = 0; i < 10; i++){
pthread_create(&threadArr[i], NULL, incByTwo, NULL);
}
pthread_join(threadArr[0], NULL);
return 0;
}
I have the following code
#include <stdio.h>
#include <thread>
#include <mutex>
class A
{
public:
A(int n) : num_workers(n) {
counter_lock = new std::mutex();
threads = new std::thread[num_workers];
for (int i = 0; i < num_workers; i++) {
threads[i] = std::thread(&A::run, this);
}
}
~A() {
delete counter_lock;
}
void start() {
go = true;
counter = 0;
total = 1000000;
while (counter < total) {};
for (int i = 0; i < num_workers; i++) {
threads[i].join();
}
}
void run() {
printf("Spinning\n");
while(1) {
if (go) {
int i;
counter_lock->lock();
i = counter++;
counter_lock->unlock();
if (i >= total) break;
}
}
printf("Done\n");
}
private:
std::mutex* counter_lock;
std::thread* threads;
int num_workers;
int counter;
int total;
bool active;
bool go;
};
int main() {
A a = A(10);
a.start();
}
In the constructor of A I create a thread pool of num_workers. They are all executing a function A::run which simply waits until it gets a signal to go and then starts incrementing the counter. The function start is meant to be synchronous with whomever called it, so in this case it should be synchronous with main. Therefore, it just idles until the counter reaches total after issuing the signal to go to all the worker threads.
The code works as expected. The counter ends up at 10000010 which makes sense because each of the 10 threads have incremented the counter once before quitting.
Is there a race condition here that I'm not noticing? Is the fact that I'm reading counter in the while(counter < total) {} loop without a lock causing any problems?
Thanks for any advice.
EDIT: I replaced the while (counter < total) {} loop with the following, perhaps more thread safe, implementation. But, very rarely, it still ends up looping forever since the value of counter hasn't updated.
while (1) {
int c;
counter_lock->lock();
c = counter;
counter_lock->unlock();
if (c >= total) break;
};
Why this cause undefined behavior?
#include <iostream>
#include <thread>
#include <vector>
std::vector<std::thread> threads(3);
void task() { std::cout<<"Alive\n";}
void spawn() {
for(int i=0; i<threads.size(); ++i)
//threads[i] = std::thread(task);
threads.emplace_back(std::thread(task));
for(int i=0; i<threads.size(); ++i)
threads[i].join();
}
int main() {
spawn();
}
If I will create threads as in commented line thread is copied/moved assignment so its fine, but why is not working when creating thread in place?
What is happening in your code is that you construct three default threads, then add three further threads.
Change:
std::vector<std::thread> threads(3);
To:
std::vector<std::thread> threads;
const size_t number_of_threads = 3;
int main() {
threads.reserve(number_of_threads);
spawn();
}
And inside spawn:
void spawn() {
for (int i = 0; i < number_of_threads; ++i) {
threads.emplace_back(std::thread(task));
}
for (int i = 0; i < threads.size(); ++i) {
threads[i].join();
}
}
When you are using emplace_back or push_back, you must not allocate the memory before, because that will call the constructor of threads. You should just reserve it.
BTW, since you are using emplace_back not push_back you can directly write:
threads.emplace_back(task);
I have a integer variable, that contains the number of threads to execute. Lets call it myThreadVar. I want to execute myThreadVar threads, and cannot think of any way to do it, without a ton of if statements. Is there any way I can create myThreadVar threads, no matter what myThreadVar is?
I was thinking:
for (int i = 0; i < myThreadVar; ++i) { std::thread t_i(myFunc); }, but that obviously won't work.
Thanks in advance!
Make an array or vector of threads, put the threads in, and then if you want to wait for them to finish have a second loop go over your collection and join them all:
std::vector<std::thread> myThreads;
myThreads.reserve(myThreadVar);
for (int i = 0; i < myThreadVar; ++i)
{
myThreads.push_back(std::thread(myFunc));
}
While other answers use vector::push_back(), I prefer vector::emplace_back(). Possibly more efficient. Also use vector::reserve(). See it live here.
#include <thread>
#include <vector>
void func() {}
int main() {
int num = 3;
std::vector<std::thread> vec;
vec.reserve(num);
for (auto i = 0; i < num; ++i) {
vec.emplace_back(func);
}
for (auto& t : vec) t.join();
}
So, obvious the best solution is not to wait previous thread to done. You need to run all of them in parallel.
In this case you can use vector class to store all of instances and after that make join to all of them.
Take a look at my example.
#include <thread>
#include <vector>
void myFunc() {
/* Some code */
}
int main()
{
int myThreadVar = 50;
std::vector <thread> threadsToJoin;
threadsToJoin.resize(myThreadVar);
for (int i = 0; i < myThreadVar; ++i) {
threadsToJoin[i] = std::thread(myFunc);
}
for (int i = 0; i < threadsToJoin.size(); i++) {
threadsToJoin[i].join();
}
}
#include <iostream>
#include <thread>
void myFunc(int n) {
std::cout << "myFunc " << n << std::endl;
}
int main(int argc, char *argv[]) {
int myThreadVar = 5;
for (int i = 0; i < myThreadVar; ++i) {
std::cout << "Launching " << i << std::endl;
std::thread t_i(myFunc,i);
t_i.detach();
}
}
g++ -std=c++11 -o 35106568 35106568.cpp
./35106568
Launching 0
myFunc 0
Launching 1
myFunc 1
Launching 2
myFunc 2
Launching 3
myFunc 3
Launching 4
myFunc 4
You need to store the thread so you can send it to join.
std::thread t[myThreadVar];
for (int i = 0; i < myThreadVar; ++i) { t[i] = std::thread(myFunc); }//Start all threads
for (int i = 0; i < myThreadVar; ++i) {t[i].join;}//Wait for all threads to finish
I think this is valid syntax, but I'm more used to c so I am unsure if I initialized the array correctly.
How to sync "for" loop counter on multithread?
If these multi thread program
void Func(int n){
for(int i=0; i<n; i++){ //at the same time with other Func()
cout << i <<endl;
}
}
void main(){
std::thread t1(Func(2));
std::thread t2(Func(2));
t1.join();
t2.join();
}
When executing Func() in parallel , I want to sync "for" loop counter "i".
For example, the program has possibility to output the result
0
1
0
1
but I want to always get the result
0
0
1
1
Can I it?
If you use OpenMP to thread your loop you can use a #pragma omp barrier statement.
In C++11 you can use a condition_variable to block all threads until they reach the same spot.
One way to do it would be to use a few variables for the threads to coordinate things (in the following they are globals, just for simplicity).
mutex m;
condition_variable c;
static int index = 0;
static int count = 2;
The index variable says at which index are the threads, and the count variable says how many threads are at the index still.
Now you're loop becomes:
void Func(int n){
for(int i=0; i<n; i++){ //at the same time with other Func()
unique_lock<mutex> l(m);
c.wait(l, [i](){return index == i;});
cout << i <<endl;
if(--count == 0)
{
++index;
count = 2;
c.notify_one();
}
}
}
Here is the full code:
#include <thread>
#include <mutex>
#include <condition_variable>
#include <iostream>
using namespace std;
mutex m;
condition_variable c;
static int index = 0;
static int count = 2;
void Func(int n){
for(int i=0; i<n; i++){ //at the same time with other Func()
unique_lock<mutex> l(m);
c.wait(l, [i](){return index == i;});
cout << i <<endl;
if(--count == 0)
{
++index;
count = 2;
c.notify_one();
}
}
}
int main(){
std::thread t1(Func, 20);
std::thread t2(Func, 20);
t1.join();
t2.join();
}
You can use a std:atomic variable and pass it to all threads.
void Func(int n, int & i){
for (; i<n; i++){ //at the same time with other Func()
cout << i << endl;
}
}
void main(){
std::atomic<int> counter = 0;
std::thread t1(Func, 2, std::ref(counter));
std::thread t2(Func, 2, std::ref(counter));
t1.join();
t2.join();
}
Also you should note that the way you are crating your threads in your example are incorrect. Secondly if you are using cout in multiple threads each cout should be guarded with a std::mutex as cout is not thread safe.