Mutex for two threads in C++ - c++

I've created two threads that use a variable declared in main via pthread_create's last argument. I want thread2 to use modify the value of that variable after thread1 is done with a set of particular instructions. I know how we can use mutex in one thread but how about two or more threads?
Refer to the following code:
#include<iostream>
#include<unistd.h>
#include<stdlib.h>
#include<pthread.h>
#define NUM 6
using namespace std;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
void *even(void *arg)
{
int sum = 0;
int count = 0;
for (int i = 1; count < NUM/2; i++)
{
if( !(i % 2) )
{
count++;
sum += i;
}
}
cout << "In Even Thread: " << sum << endl;
pthread_mutex_lock(&mutex);
*((int*)arg) = sum;
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&cond);
}
void *odd(void *arg)
{
int sum = 0;
int count = 0;
for (int i = 1; count < NUM/2; i++)
{
if( i % 2 )
{
count++;
sum += i;
}
}
cout << "In Odd Thread: " << sum << endl;
pthread_cond_wait(&cond, &mutex);
*((int*)arg) = *((int*)arg) + sum;
}
int main()
{
int mainSum = 0;
pthread_t tidO, tidE;
pthread_create(&tidO, NULL, odd, (void *)&mainSum);
pthread_create(&tidE, NULL, even, (void *)&mainSum);
pthread_join(tidO, NULL);
pthread_join(tidE, NULL);
cout << "Sum of first " << NUM << " Natural Numbers: " << mainSum << endl;
return 0;
}

You should lock mutex before accessing the variable and unlock after you finish you finish you job with the variable. Use lock_guard to keep mutex locked and use brackets for lock_guard lifetime. http://www.cplusplus.com/reference/mutex/lock_guard/
std::mutex mtx; //global mutex
int v; //global variable;
int k;
...
//repeat this code in each thread to access the variable
{
std::lock_guard<std::mutex> lck (mtx);
//access the variable;
k = v; //read global variable or
v = k; //write
}

Your use case needs a condition variable combined with a mutex.
http://en.cppreference.com/w/cpp/thread/condition_variable

You should create mutex in same place as shared variable. In your case it is main function.
Then you need to share this mutex in all threads which are accessing shared variable.
You can share this mutex over global variable or better in same attribute as shared variable. But you will have to define structure where you place variable and mutex together.
Update
You should lock mutex pthread_mutex_lock(&mutex); before pthread_cond_wait(&cond, &mutex);
The pthread_cond_signal() and pthread_cond_broadcast() functions have no effect if there are no threads currently blocked on cond.

Related

Can't tell if Mutex Lock is kicking in or not?

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;
}

C++ threads. Why always executes last thread?

Why only last threads executes every time? I'm trying to divide grid into N workers, half of grid always not touchable and other part always proceed by 1 last created thread. Should I use an array instead of vector? Locks also do not help to resolve this problem.
#include <iostream>
#include <unistd.h>
#include <vector>
#include <stdio.h>
#include <cstring>
#include <future>
#include <thread>
#include <pthread.h>
#include <mutex>
using namespace std;
std::mutex m;
int main(int argc, char * argv[]) {
int iterations = atoi(argv[1]), workers = atoi(argv[2]), x = atoi(argv[3]), y = atoi(argv[4]);
vector<vector<int> > grid( x , vector<int> (y, 0));
std::vector<thread> threads(workers);
int start, end, lastworker, nwork;
int chunkSize = y/workers;
for(int t = 0; t < workers; t++){
start = t * chunkSize;
end = start + chunkSize;
nwork = t;
lastworker = workers - 1;
if(lastworker == t){
end = y; nwork = workers - 1;
}
threads[nwork] = thread([&start, &end, &x, &grid, &t, &nwork, &threads] {
cout << " ENTER TO THREAD -> " << threads[nwork].get_id() << endl;
for (int i = start; i < end; ++i)
{
for (int j = 0; j < x; ++j)
{
grid[i][j] = t;
}
}
sleep(2);
});
cout << threads[nwork].get_id() << endl;
}
for(auto& th : threads){
th.join();
}
for (int i = 0; i < y; ++i)
{
for (int j = 0; j < x; ++j)
{
cout << grid[i][j];
}
cout << endl;
}
return(0);
}
[&start, &end, &x, &grid, &t, &nwork, &threads]
This line is the root of the problem. You are capturing all the variables by reference, which is not what you want to do.
As a consequence, each thread uses the same variables, which is also not what you want.
You should only capture grid and threads by reference, the other variables should be captured by value ('copied' into the lambda)
[start, end, x, &grid, t, nwork, &threads]
Also, you are accessing grid wrong everywhere: change grid[i][j] to grid[j][i]
thread([&start, &end, &x, &grid, &t, &nwork, &threads] {
=======
The lambda closure that gets executed by every thread captures a reference to nwork.
Which means that as the for loop iterates and starts every thread, each captured thread will always reference the current value of nwork, at the time it does.
As such, the outer loop probably quickly finishes creating each thread object before all the threads actually initialize and actually enter the lambda closure, and each closure sees the same value of nwork, because it is captured by reference, which is the last thread id.
You need to capture nwork by value instead of by reference.
You're passing all the thread parameters are references to the thread lambda. However, when the loop continues in the main thread, the thread parameter variables change, which changes their values in the threads as well, messing up all the previously-created threads.

Race conditions in threads despite mutexlocking

This code calculates the sum of all integers in an array, evenly dividing the work between multiple threads. However every once in a while the thread numbers as well as the localsum of the thread are messed up. I am assuming it's because void* param and globalindex are accessed by multiple threads at the same time. What does not make sense is the fact that it happens, even though I mutexlocked every global variable in this code.
How do I fix this?
#include<string>
#include<iostream>
#include<fstream>
#include<unistd.h>
#include<pthread.h>
#include<stdlib.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
using namespace std;
int y =0;
int sum=0;
int array[1000000];
int x=0;
int leftoverHandle = 0;
int globalindex = 0;
int eachThreadHandles =0;
void* add(void* param){
pthread_mutex_lock(&mutex);
int localindexup = globalindex + eachThreadHandles;
int localindexdown = globalindex;
int localsum=0;
long localparam = (long)param;
if(y != leftoverHandle ){
localindexup++;
y++;
}
pthread_mutex_unlock(&mutex);
while(localindexdown<localindexup){
pthread_mutex_lock(&mutex);
sum = sum+array[localindexdown];
localsum = localsum+array[localindexdown];
localindexdown++;
pthread_mutex_unlock(&mutex);
}
pthread_mutex_lock(&mutex);
globalindex = localindexdown;
printf("Thread %ld", localparam);
printf(": %d\n", localsum);
pthread_mutex_unlock(&mutex);
}
int main(int argc, char ** argv){
if(argc != 3){
cout<<"Incorrect number of argument";
exit(1);
}
string line;
string f = argv[1];
const char *filename = f.c_str();
int maxthreads = atoi(argv[2]);
FILE* inFile = fopen(filename,"r");
int i=0;
if(inFile == NULL){
cout<<"fopen failed"<<endl;
}
fscanf(inFile, "%d",&i);
while(!feof(inFile)){
array[x]=i;
x +=1;
fscanf(inFile,"%d",&i);
}
fclose(inFile);
pthread_t id[maxthreads];
leftoverHandle = x%maxthreads;
eachThreadHandles = (x - leftoverHandle)/maxthreads;
for(long i=0; i< maxthreads;i++){
long status = pthread_create(&id[i], NULL, add, (void*) i);
if(status){
printf("Error creating thread! \n");
exit(0);
}
}
for(long i=0; i<maxthreads;i++){
pthread_join(id[i], NULL);
}
cout<<"Sum="<<sum<<endl;
return 0;
}
The problem is that you are not updating globalindex right after initializing localindexup and localindexdown per each thread, i.e in the first critical section.
You have three critical sections in your code.
Imagine that thread0 runs the first critical section, then thread1 preempts thread0 right after thread0 releases the lock of the first critical section. But because you are setting globalindex to localindexdown in the third critical section, not the first one, thread1 will still see globalindex=0, just like thread0, so it is going to recalculate the same sum as thread0. You should put globalindex = localindexdown; into the first critical section.
Actually there is no need for the third critical section at all:
pthread_mutex_lock(&mutex);
int localindexup = globalindex + eachThreadHandles;
int localindexdown = globalindex;
int localsum=0;
long localparam = (long)param;
if(y != leftoverHandle ){
localindexup++;
y++;
}
globalindex = localindexdown; //<--- MOVED HERE
pthread_mutex_unlock(&mutex);
And forget my comment about the loop, I made a mistake: while(localindexdown<localindexup) can be safely preempted because the variables are not shared among threads. You can just improve the performance a bit by reducing the mutexed region to include only shared data:
while(localindexdown<localindexup)
{
pthread_mutex_lock(&mutex);
sum = sum+array[localindexdown];
pthread_mutex_unlock(&mutex); //<--- MOVED HERE
localsum = localsum+array[localindexdown];
localindexdown++;
}

Cannot understand pthread_cond_wait/signal/broadcast

I'm trying to understand pthread conditions.
For doing so, I wrote a very basic program but, no matter how many manuals and explanations I read, I just cannot understand how things work.
#include <iostream>
#include <pthread.h>
using namespace std;
#define NT 3
#define ITERATIONS 5
int countDone=0;
int a[NT] = {10, 20, 30};
pthread_cond_t doneCond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t doneMutex = PTHREAD_MUTEX_INITIALIZER;
void * thread_start(void* num){
int currIt=0;
while(currIt < ITERATIONS){
cout << pthread_self() << "my number is " << a[(int)num] << endl;
a[(int)num]++;
pthread_mutex_lock(&doneMutex);
countDone++;
if(countDone == NT)
pthread_cond_signal(&doneCond);
while(countDone != 0)
pthread_cond_wait(&doneCond, &doneMutex);
pthread_mutex_unlock(&doneMutex);
currIt++;
}
pthread_exit(NULL);
}
int main(){
pthread_t tidVec[NT];
int i, currIt=0, ret;
//creating threads
for(i=0; i<NT; i++)
pthread_create(&tidVec[i], NULL, &thread_start, (void*)i);
while(currIt < ITERATIONS){
cout << "---Iteration " << currIt << endl;
pthread_mutex_lock(&doneMutex);
while(countDone < NT)
pthread_cond_wait(&doneCond, &doneMutex);
countDone = 0;
pthread_cond_broadcast(&doneCond);
pthread_mutex_unlock(&doneMutex);
currIt++;
}
//waiting for threads termination
for(i=0; i<NT; i++)
pthread_join(tidVec[i], (void**)&ret);
pthread_cond_destroy(&doneCond);
pthread_mutex_destroy(&doneMutex);
return 0;
}
What I want it to do is: at each iteration, every thread prints the number assigned to itself in the array a, increments the value and then increments the counter countDone (which counts how many threads have already done their job).
The last thread that finishes its job "tells" the main the they all are done.
The main sets the counter to zero, so that a new iteration can begin.
And so on for 5 iterations.
What I get as an output is:
---Iteration 0
3057584960my number is 30
3065977664my number is 20
3074370368my number is 10
---Iteration 1
3057584960my number is 31
and then it gets stuck.
Can you please help me figure out what is going on here?
Thank you.

How to sync "for" loop counter in multithread?

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.