Reputation: 49
I am trying to grasp the understanding of mutex locks. I am solving a mathematical equation (a+b) * (c+d) / e
using three different threads, namely addition, multiplication, and division. As a start I have written this code. What I had in mind is that the addition thread should run first and all other threads should be blocked but it's giving a random output. Here is the code I have written so far.
#include <iostream>
#include <pthread.h>
using std::cout, std::endl;
pthread_mutex_t mutex1;
void *Division(void *arg_div)
{
int *input =(int *)arg_div;
int result = input[0]/input[1];
cout<<"Final result"<<endl;
cout << result ;
pthread_exit(NULL);
}
void *Multiplication(void *arg_mul)
{
int *input =(int *)arg_mul;
int arg1[2];
arg1[0]=input[0]*input[1];
arg1[1]=input[2];
cout<<"Multiplication results are"<<endl;
cout<<arg1[0];
cout<<arg1[1];
pthread_exit(NULL);
}
void *Addition(void *arg_add)
{
pthread_mutex_lock(&mutex1);
cout<<"Addition Thread is acquring lock"<<endl;
int *input =(int *)arg_add;
//my critical section
int arg[3];
arg[0]=input[0]+input[1];
arg[1]=input[2]+input[3];
pthread_mutex_unlock(&mutex1);
arg[2]=input[4];
cout<<"output of add function"<<endl;
cout<<arg[0]<<endl;
cout<<arg[1]<<endl;
cout<<arg[2]<<endl;
pthread_exit(NULL);
}
int main()
{
int values[5]={6,5,4,3,2};
pthread_t add;
pthread_t multiply;
pthread_t divide;
pthread_create(&add,NULL,Addition,(void*)values);
pthread_create(&multiply,NULL,Multiplication,(void*)values);
pthread_create(÷,NULL,Division,(void*)values);
pthread_join(add,NULL);
pthread_join(multiply,NULL);
pthread_join(divide,NULL);
return 0;
}
I want only addition thread to execute first followed by multiplication thread and then finally division.
Upvotes: 3
Views: 1881
Reputation: 1224
For computing (a+b) x (c+d) / e, first addition should be done and then multiplication, and finally the division.
Let us have three semaphores, sem-add with initial value 1, and sem-multiply and sem-divide, both with initial value, 0.
The code for three arithmetic functions should be,
addition ()
{
P (sem-add);
...
...
V (sem-multiply);
}
multiply ()
{
P (sem-multiply);
....
....
V (sem-divide);
}
division ()
{
P (sem-divide);
....
....
V (sem-add);
}
For more details see, Semaphore Basics
Upvotes: 0
Reputation: 118077
Here's a version using std::thread
and condition variables instead of using the C interface to pthread
.
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
using std::cout, std::endl;
std::mutex m;
std::condition_variable cv_div_done, cv_mul_done, cv_add_done;
// these boolean variables are needed to detect Spurious wakeups
bool b_div_done=false, b_mul_done=false, b_add_done=false;
void Division(int *input) {
std::unique_lock lk(m); // acquire mutex lock
// wait() releases the lock until the condition is met
// and here we wait for Multiplication to be done:
cv_mul_done.wait(lk, []{ return b_mul_done; });
// here we have the mutex lock again
input[0] = input[0]/input[1];
cout<<"Final result"<<endl;
cout << input[0] << "\n";
// signal those waiting for div to be done
b_div_done = true;
cv_div_done.notify_all();
} // lock released automatically when it goes out of scope
void Multiplication(int *input) {
std::unique_lock lk(m);
cv_add_done.wait(lk, []{ return b_add_done; });
input[0]=input[0]*input[1];
input[1]=input[2];
cout<<"Multiplication results are"<<endl;
cout << input[0] << "\n";
cout << input[1] << "\n";
b_mul_done = true;
cv_mul_done.notify_all();
}
void Addition(int *input) {
std::unique_lock lk(m); // not really needed in this case
input[0]=input[0]+input[1];
input[1]=input[2]+input[3];
input[2]=input[4];
cout<<"output of add function"<<endl;
cout<<input[0]<<endl;
cout<<input[1]<<endl;
cout<<input[2]<<endl;
b_add_done = true;
cv_add_done.notify_all();
}
int main() { // (a+b) x (c+d) / e
int values[5]={6,5,4,3,2};
std::thread add(Addition, values);
std::thread mul(Multiplication, values);
std::thread div(Division, values);
/* if you'd like to run the threads detached (to not have to join them),
* you can wait for the final result here */
/*
std::unique_lock lk(m);
cv_div_done.wait(lk, []{ return b_div_done; });
*/
add.join();
mul.join();
div.join();
}
Output:
output of add function
11
7
2
Multiplication results are
77
2
Final result
38
Upvotes: 0
Reputation:
There are two problems in your code.
1) Only one thread uses the lock. This does not affect any other thread, which is therefore free to run at any time.
2) A mutex is for mutual exclusion, not sequencing of execution. If you want one thread to run before another, you'll have to arrange some way for that to happen. For example, "thread 2" could wait on a condition that "thread 1" has finished; "thread 1" would signal that condition appropriately. Or you could look into the producer/consumer model of semaphore use: the addition thread is producing results for the multiplication thread to consume.
Upvotes: 1