I am attempting to learn about semaphores and multi-threading. The example I am working with creates 1 to t threads with each thread pointing to the next and the last thread pointing to the first thread. This program allows each thread to sequentially take a turn until all threads have taken n turns. That is when the program ends. The only problem is in the tFunc function, I am busy waiting until it is a specific thread's turn. I want to know how to use semaphores in order to make all the threads go to sleep and waking up a thread only when it is its turn to execute to improve efficiency.
int turn = 1;
int counter = 0;
int t, n;
struct tData {
int me;
int next;
};
void *tFunc(void *arg) {
struct tData *data;
data = (struct tData *) arg;
for (int i = 0; i < n; i++) {
while (turn != data->me) {
}
counter++;
turn = data->next;
}
}
int main (int argc, char *argv[]) {
t = atoi(argv[1]);
n = atoi(argv[2]);
struct tData td[t];
pthread_t threads[t];
int rc;
for (int i = 1; i <= t; i++) {
if (i == t) {
td[i].me = i;
td[i].next = 1;
}
else {
td[i].me = i;
td[i].next = i + 1;
}
rc = pthread_create(&threads[i], NULL, tFunc, (void *)&td[i]);
if (rc) {
cout << "Error: Unable to create thread, " << rc << endl;
exit(-1);
}
}
for (int i = 1; i <= t; i++) {
pthread_join(threads[i], NULL);
}
pthread_exit(NULL);
}
Uses mutexes and condition variables. Here's a working example:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
int turn = 1;
int counter = 0;
int t, n;
struct tData {
int me;
int next;
};
pthread_mutex_t mutex;
pthread_cond_t cond;
void *tFunc(void *arg)
{
struct tData *data;
data = (struct tData *) arg;
pthread_mutex_lock(&mutex);
for (int i = 0; i < n; i++)
{
while (turn != data->me)
pthread_cond_wait(&cond, &mutex);
counter++;
turn = data->next;
printf("%d goes (turn %d of %d), %d next\n", data->me, i+1, n, turn);
pthread_cond_broadcast(&cond);
}
pthread_mutex_unlock(&mutex);
}
int main (int argc, char *argv[]) {
t = atoi(argv[1]);
n = atoi(argv[2]);
struct tData td[t + 1];
pthread_t threads[t + 1];
int rc;
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond, NULL);
for (int i = 1; i <= t; i++)
{
td[i].me = i;
if (i == t)
td[i].next = 1;
else
td[i].next = i + 1;
rc = pthread_create(&threads[i], NULL, tFunc, (void *)&td[i]);
if (rc)
{
printf("Error: Unable to create thread: %d\n", rc);
exit(-1);
}
}
void *ret;
for (int i = 1; i <= t; i++)
pthread_join(threads[i], &ret);
}
Use N+1 semaphores. On startup, thread i waits on semaphore i. When woken up it "takes a turnand signals semaphorei + 1`.
The main thread spawns the N, threads, signals semaphore 0 and waits on semaphore N.
Pseudo code:
sem s[N+1];
thread_proc (i):
repeat N:
wait (s [i])
do_work ()
signal (s [i+1])
main():
for i in 0 .. N:
spawn (thread_proc, i)
repeat N:
signal (s [0]);
wait (s [N]);
Have one semaphore per thread. Have each thread wait on its semaphore, retrying if sem_wait returns EINTR. Once it's done with its work, have it post to the next thread's semaphore. This avoids the "thundering herd" behaviour of David's solution by waking only one thread at a time.
Also notice that, since your semaphores will never have a value larger than one, you can use a pthread_mutex_t for this.
Related
I'm having an attempt at the famous producer-consumer problem in c++ and I have came up with an implementation like this...
#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <ctime>
void *consumeThread(void *i);
void *produceThread(void *i);
using std::cout;
using std::endl;
//Bucket size
#define Bucket_size 10
int buckets[Bucket_size];
pthread_mutex_t lock;
pthread_cond_t consume_now, produce_now;
time_t timer;
int o = 0;
int p = 0;
int main()
{
int i[5] = {1, 2, 3, 4, 5};
pthread_t consumer[5];
pthread_t producer[5];
pthread_mutex_init(&lock, nullptr);
pthread_cond_init(&consume_now, nullptr);
pthread_cond_init(&produce_now, nullptr);
timer = time(nullptr) + 10;
srand(time(nullptr));
for (int x = 0; x < 5; x++)
{
pthread_create(&producer[x], nullptr, &produceThread, &i[x]);
}
for (int x = 0; x < 5; x++)
{
pthread_create(&consumer[x], nullptr, &consumeThread, &i[x]);
}
pthread_cond_signal(&produce_now);
for (int x = 0; x < 5; x++)
{
pthread_join(producer[x], nullptr);
pthread_join(consumer[x], nullptr);
}
pthread_mutex_destroy(&lock);
pthread_cond_destroy(&consume_now);
pthread_cond_destroy(&produce_now);
return 0;
}
void *consumeThread(void *i)
{
bool quit = false;
while (!quit)
{
pthread_mutex_lock(&lock);
pthread_cond_wait(&consume_now, &lock);
printf("thread %d consuming element at array[%d] : the element is %d \n", *((int *)i), o, buckets[o]);
buckets[o] = 0;
p++;
printArray();
usleep(100000);
pthread_cond_signal(&produce_now);
pthread_mutex_unlock(&lock);
quit = time(nullptr) > timer;
}
return EXIT_SUCCESS;
}
void *produceThread(void *i)
{
int a = 0;
bool quit = false;
while (!quit)
{
o = p % 10;
buckets[o] = (rand() % 20) + 1;
printf("thread %d adding element in array[%d] : the element is %d \n", *((int *)i), o, buckets[o]);
a++;
printArray();
usleep(100000);
quit = time(nullptr) > timer;
}
return EXIT_SUCCESS;
}
currently this solution has 5 producer threads and 5 consumer threads, however it only lets 1 thread produce and 1 thread consume at a time, is there a way to make 5 of the producer and consumer threads work concurrently?
Example output from the program:
thread 1 adding element in array[0] : the element is 6
[6,0,0,0,0,0,0,0,0,0]
Your first problem is that you are treating condition variables as if they have memory. In your main(), you pthread_cond_signal(), but at that point, you have no idea if any of your threads are waiting upon that condition. Since condition variables do not have memory, your signal may well be lost.
Your second problem is that o is effectively protected by the condition; since each consumer uses it; and each producer modifies it, you can neither permit multiple producers or consumers to execute concurrently.
Your desired solution amounts to a queue which you inject o's into from the producers; and collect them in the consumers. That way, your concurrency is gated by your ability to produce o's.
Now all 5 threads are running. However after 5 threads are run for the first time. Only first thread (thread # 0) runs infinitely blocking rest of the threads. I only see thread # 0 idle (waiting) and consuming (eating) and again entering into infinite loop other 4 threads do not get a chance after 1st round.
struct sem_t_ * sem[5];
struct sem_t_ * lock;
class Phil
{
public:
Phil()
{
isThinking = isEating = 0;
mId = 0;
}
//~Phil();
bool isThinking;
bool isEating;
int mId;
void setID(int id)
{
mId = id;
}
void think()
{
isThinking = 1;
isEating = 0;
cout<<"Thread "<<mId<<" is idle!.\n";
}
void eat()
{
isThinking = 0;
isEating = 1;
cout<<"Thread "<<mId<<" is consuming!.\n";
}
};
void pause()
{
Sleep(1000);
}
Phil* pArray = new Phil[5];
void* thread_Create(void*param)
{
int value = 0;
int* id = (int*)param;
for(;;)
{
cout<<"Thread Id = "<<*id<<" running.\n";
pArray[*id].think();
sem_wait(&lock);
int left = *id;
int right = (*id)+1;
if( right > 4) right = 0;
//cout<<"Left = "<<left<<" Right = "<<right<<endl;
sem_getvalue(&sem[left],&value) ;
//cout<<"Left Value = "<<value<<endl;
if( value != 1 )
{
sem_post(&lock);
continue;
}
if( value != 1 )
{
sem_post(&lock);
continue;
}
sem_wait(&sem[left]);
sem_wait(&sem[right]);
pArray[*id].eat();
sem_post(&sem[left]);
sem_post(&sem[right]);
sem_post(&lock);
pause();
}
return 0;
}
void main(void)
{
int i = 0;
for(i=0; i< 5;i++)
{
pArray[i].setID(i);
sem_init(&sem[i],0,1);
}
sem_init(&lock, 0, 5);
pthread_t threads[5];
for(i=0; i< 5;i++)
{
pthread_create(&threads[i],NULL,thread_Create, (void*)&i);
pause();
}
for(i=0; i< 5;i++)
{
pthread_join(threads[i], NULL); //Main thread will block until child threads exit!
}
for(i=0; i< 5;i++)
{
sem_destroy(&sem[i]);
}
sem_destroy(&lock);
}
Your problem is in this line:
pthread_join(threads[i], NULL); //Main thread will block until child threads exit!
It is doing exactly what your comment says - your main thread creates one thread (thread 0) and then blocks until thread 0 finishes, which it never does. So your main program never creates any more threads.
The solution is to move the pthread_join calls into another loop. i.e. create all the threads first, then wait for them all to finish.
I am experimenting with pthreads. I am trying to create three threads and have them operate on a global char buffer. I am using mutex lock and unlock for their critical sections. The program flow should go: Main spawns three threads. Thread one locks, initializes the buffer, prints it out, signals thread two, and unlocks. Thread two enters its critical section operates on the buffer and signals thread three, etc. It seems to work, sometimes. Other times, it seems like it is getting suck in a spin lock. Any help in the right direction would be great. Thanks.
#include <pthread.h>
#include <string.h>
#include <unistd.h>
#include <iostream>
using namespace std;
const int num_threads = 3;
char buffer[100];
pthread_mutex_t buffer_mutex = pthread_mutex_initializer;
pthread_cond_t buffer_cond = pthread_cond_initializer;
void* firstthreadfunc(void* proc) {
string a = "data received";
pthread_mutex_lock(&buffer_mutex);
sleep(1);
cout<<"threadone"<<endl;
for(int i = 0;i<14;i++){
buffer[i] = a[i];
cout<<buffer[i];
}
cout<<endl;
pthread_cond_signal(&buffer_cond);
pthread_mutex_unlock(&buffer_mutex);
return null;
}
void* secondthreadfunc(void* proc) {
string a = "data processed";
pthread_mutex_lock(&buffer_mutex);
pthread_cond_wait(&buffer_cond, &buffer_mutex);
sleep(1);
cout<<"threadtwo"<<endl;
for(int i = 0; i<15 ;i++){
buffer[i] = a[i];
cout<<buffer[i];
}
cout<<endl;
pthread_cond_signal(&buffer_cond);
pthread_mutex_unlock(&buffer_mutex);
return null;
}
void* thirdthreadfunc(void* proc) {
string a = "data sent";
pthread_mutex_lock(&buffer_mutex);
pthread_cond_wait(&buffer_cond, &buffer_mutex);
sleep(1);
cout<<"thread three"<<endl;
for(int i = 0;i<9;i++){
buffer[i] = a[i];
cout<<buffer[i];
}
cout<<endl;
pthread_cond_signal(&buffer_cond);
pthread_mutex_unlock(&buffer_mutex);
return null;
}
int main() {
pthread_t p_threadone, p_threadtwo, p_threadthree;;
pthread_attr_t attr;
pthread_attr_init(&attr);
for(int i = 0;i<100;i++){
buffer[i] = 'a';
}
//create threads
cout<<"creating threads"<<endl;
pthread_create(&p_threadone, &attr, firstthreadfunc, null);
pthread_create(&p_threadtwo, &attr, secondthreadfunc, null);
pthread_create(&p_threadthree, &attr, thirdthreadfunc, null);
//terminate threads
pthread_join(p_threadone,null);
pthread_join(p_threadtwo,null);
pthread_join(p_threadthree,null);
return 0;
}
Thanks WhozCraig and Tony, your answers resolved the issue. I understand what I was doing wrong.
First, where you're stuck. The following line in either thread2 or thread3 is the sticking point:
pthread_cond_wait(&buffer_cond, &buffer_mutex);
And by now you're asking, "Why?" Because your mistaking a condition variable as a state; not a signaling mechanism. Condition variables are intended to be used to signal interested waiters of change in state of something else: the predicate. You have none. Consider the following modified version of your code.
This uses two predicate values (I advise you stick with one per condvar until you become more comfortable with them; start simple), protecting them with the same mutex and signaling their change with the same condition variable. The important thing to note is that we don't wait on the condition variable until we know the predicate we're waiting for is not ready yet. And since we have the mutex locked, we can safely do check that predicate:
#include <iostream>
#include <string>
#include <unistd.h>
#include <pthread.h>
using namespace std;
const int NUM_THREADS = 3;
char buffer[100];
bool bDataReady = false;
bool bDataWaiting = false;
pthread_mutex_t buffer_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t buffer_cond = PTHREAD_COND_INITIALIZER;
void* firstThreadFunc(void* proc)
{
string a = "Data Received";
pthread_mutex_lock(&buffer_mutex);
cout<<"ThreadOne"<<endl;
std::copy(a.begin(), a.end(), buffer);
buffer[a.size()] = 0;
cout << buffer << endl;
bDataReady = true;
pthread_cond_broadcast(&buffer_cond);
pthread_mutex_unlock(&buffer_mutex);
return NULL;
}
void* secondThreadFunc(void* proc)
{
string a = "Data Processed";
pthread_mutex_lock(&buffer_mutex);
while (!bDataReady)
pthread_cond_wait(&buffer_cond, &buffer_mutex);
cout<<"ThreadTwo"<<endl;
std::copy(a.begin(), a.end(), buffer);
buffer[a.size()] = 0;
cout << buffer << endl;
bDataReady = false;
bDataWaiting = true;
pthread_cond_broadcast(&buffer_cond);
pthread_mutex_unlock(&buffer_mutex);
return NULL;
}
void* thirdThreadFunc(void* proc)
{
string a = "Data Sent";
pthread_mutex_lock(&buffer_mutex);
while (!bDataWaiting)
pthread_cond_wait(&buffer_cond, &buffer_mutex);
cout<<"Thread Three"<<endl;
std::copy(a.begin(), a.end(), buffer);
buffer[a.size()] = 0;
cout << buffer << endl;
bDataWaiting = false;
pthread_cond_broadcast(&buffer_cond);
pthread_mutex_unlock(&buffer_mutex);
return NULL;
}
int main() {
pthread_t p_threadOne, p_threadTwo, p_threadThree;;
pthread_attr_t attr;
pthread_attr_init(&attr);
for(int i = 0;i<100;i++){
buffer[i] = 'a';
}
//create Threads
cout<<"creating threads"<<endl;
pthread_create(&p_threadOne, &attr, firstThreadFunc, NULL);
pthread_create(&p_threadTwo, &attr, secondThreadFunc, NULL);
pthread_create(&p_threadThree, &attr, thirdThreadFunc, NULL);
//terminate Threads
pthread_join(p_threadOne,NULL);
pthread_join(p_threadTwo,NULL);
pthread_join(p_threadThree,NULL);
return 0;
}
Output
creating threads
ThreadOne
Data Received
ThreadTwo
Data Processed
Thread Three
Data Sent
I'm working on a school lab and we are instructed to create a recursive mutex lock for a counting program. I've written some code (which doesn't work), but I think that this is mostly because I do not understand the real idea behind using a recursive mutex lock. Could anyone elaborate what a recursive mutex lock should do/look like?
General Note: I'm not asking for an answer, just some clarification as to what recursive mutex lock should do.
Also, if anyone is curious, here is the code required for this. The code that I am editing/implementing is the recmutex.c.
recmutex.h
#include <pthread.h>
/*
* The recursive_mutex structure.
*/
struct recursive_mutex {
pthread_cond_t cond;
pthread_mutex_t mutex; //a non-recursive pthread mutex
pthread_t owner;
unsigned int count;
unsigned int wait_count;
};
typedef struct recursive_mutex recursive_mutex_t;
/* Initialize the recursive mutex object.
*Return a non-zero integer if errors occur.
*/
int recursive_mutex_init (recursive_mutex_t *mu);
/* Destroy the recursive mutex object.
*Return a non-zero integer if errors occur.
*/
int recursive_mutex_destroy (recursive_mutex_t *mu);
/* The recursive mutex object referenced by mu shall be
locked by calling pthread_mutex_lock(). When a thread
successfully acquires a mutex for the first time,
the lock count shall be set to one and successfully return.
Every time a thread relocks this mutex, the lock count
shall be incremented by one and return success immediately.
And any other calling thread can only wait on the conditional
variable until being waked up. Return a non-zero integer if errors occur.
*/
int recursive_mutex_lock (recursive_mutex_t *mu);
/* The recursive_mutex_unlock() function shall release the
recursive mutex object referenced by mu. Each time the owner
thread unlocks the mutex, the lock count shall be decremented by one.
When the lock count reaches zero, the mutex shall become available
for other threads to acquire. If a thread attempts to unlock a
mutex that it has not locked or a mutex which is unlocked,
an error shall be returned. Return a non-zero integer if errors occur.
*/
int recursive_mutex_unlock (recursive_mutex_t *mu);
recmutex.c: contains the functions for the recursive mutex
#include <stdio.h>
#include <pthread.h>
#include <errno.h>
#include "recmutex.h"
int recursive_mutex_init (recursive_mutex_t *mu){
int err;
err = pthread_mutex_init(&mu->mutex, NULL);
if(err != 0){
perror("pthread_mutex_init");
return -1;
}else{
return 0;
}
return 0;
}
int recursive_mutex_destroy (recursive_mutex_t *mu){
int err;
err = pthread_mutex_destroy(&mu->mutex);
if(err != 0){
perror("pthread_mutex_destroy");
return -1;
}else{
return 1;
}
return 0;
}
int recursive_mutex_lock (recursive_mutex_t *mu){
if(mutex_lock_count == 0){
pthread_mutex_lock(&mu->mutex);
mu->count++;
mu->owner = pthread_self();
printf("%s", mu->owner);
return 0;
}else if(mutex_lock_count > 0){
pthread_mutex_lock(&mu->mutex);
mu->count++;
mu->owner = pthread_self();
return 0;
}else{
perror("Counter decremented incorrectly");
return -1;
}
}
int recursive_mutex_unlock (recursive_mutex_t *mu){
if(mutex_lock_count <= 0){
printf("Nothing to unlock");
return -1;
}else{
mutex_lock_count--;
pthread_mutex_unlock(&mu->mutex);
return 0;
}
}
count_recursive.cc: The counting program mentioned above. Uses the recmutex functions.
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#include <assert.h>
#include <string.h>
#include "recmutex.h"
//argument structure for the thread
typedef struct _arg_{
int n1;
int n2;
int ntimes;
}Arg;
int count; //global counter
recursive_mutex_t mutex; //the recursive mutex
void do_inc(int n){
int ret;
if(n == 0){
return;
}else{
int c;
ret = recursive_mutex_lock(&mutex);
assert(ret == 0);
c = count;
c = c + 1;
count = c;
do_inc(n - 1);
ret = recursive_mutex_unlock(&mutex);
assert(ret == 0);
}
}
/* Counter increment function. It will increase the counter by n1 * n2 * ntimes. */
void inc(void *arg){
Arg * a = (Arg *)arg;
for(int i = 0; i < a->n1; i++){
for(int j = 0; j < a->n2; j++){
do_inc(a->ntimes);
}
}
}
int isPositiveInteger (const char * s)
{
if (s == NULL || *s == '\0' || isspace(*s))
return 0;
char * p;
int ret = strtol (s, &p, 10);
if(*p == '\0' && ret > 0)
return 1;
else
return 0;
}
int test1(char **argv){
printf("==========================Test 1===========================\n");
int ret;
//Get the arguments from the command line.
int num_threads = atoi(argv[1]); //The number of threads to be created.
int n1 = atoi(argv[2]); //The outer loop count of the inc function.
int n2 = atoi(argv[3]); //The inner loop count of the inc function.
int ntimes = atoi(argv[4]); //The number of increments to be performed in the do_inc function.
pthread_t *th_pool = new pthread_t[num_threads];
pthread_attr_t attr;
pthread_attr_init( &attr );
pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
ret = recursive_mutex_init(&mutex);
assert(ret == 0);
printf("Start Test. Final count should be %d\n", num_threads * n1 * n2 * ntimes );
// Create threads
for(int i = 0; i < num_threads; i++){
Arg *arg = (Arg *)malloc(sizeof(Arg));
arg->n1 = n1;
arg->n2 = n2;
arg->ntimes = ntimes;
ret = pthread_create(&(th_pool[i]), &attr, (void * (*)(void *)) inc, (void *)arg);
assert(ret == 0);
}
// Wait until threads are done
for(int i = 0; i < num_threads; i++){
ret = pthread_join(th_pool[i], NULL);
assert(ret == 0);
}
if ( count != num_threads * n1 * n2 * ntimes) {
printf("\n****** Error. Final count is %d\n", count );
printf("****** It should be %d\n", num_threads * n1 * n2 * ntimes );
}
else {
printf("\n>>>>>> O.K. Final count is %d\n", count );
}
ret = recursive_mutex_destroy(&mutex);
assert(ret == 0);
delete [] th_pool;
return 0;
}
int foo(){
int ret;
printf("Function foo\n");
ret = recursive_mutex_unlock(&mutex);
assert(ret != 0);
return ret;
}
//test a thread call unlock without actually holding it.
int test2(){
int ret;
printf("\n==========================Test 2==========================\n");
pthread_t th;
pthread_attr_t attr;
pthread_attr_init( &attr );
pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
ret = recursive_mutex_init(&mutex);
ret = pthread_create(&th, &attr, (void * (*)(void *))foo, NULL);
printf("Waiting for thread to finish\n");
ret = pthread_join(th, NULL);
assert(ret == 0);
return 0;
}
int main( int argc, char ** argv )
{
int ret;
count = 0;
if( argc != 5 ) {
printf("You must enter 4 arguments. \nUsage: ./count_recursive num_threads n1 n2 ntimes\n");
return -1;
}
if(isPositiveInteger(argv[1]) != 1 || isPositiveInteger(argv[2]) != 1 || isPositiveInteger(argv[3]) != 1 || isPositiveInteger(argv[4]) != 1 ){
printf("All the 4 arguments must be positive integers\n");
return -1;
}
test1(argv);
test2();
return 0;
}
The idea of a recursive mutex is that it can be successfully relocked by the thread that is currently holding the lock. For example:
if I had some mutexes like this (this is pseudocode):
mutex l;
recursive_mutex r;
In a single thread if I did this:
l.lock();
l.lock(); // this would hang the thread.
but
r.lock();
r.lock();
r.lock(); // this would all pass though with no issue.
In implimenting a recursive mutex you need to check what threadId has locked it, if it was locked, and if it matches the current thread id, return success.
The point of a recursive mutex, is to let you write this:
recursive_mutext_t rmutex;
void foo(...) {
recursive_lock_lock(&rmutex);
...
recursive_lock_unlock(&rmutex);
}
void bar(...) {
recursive_lock_lock(&rmutex);
...
foo(...);
...
recursive_lock_unlock(&rmutex);
}
void baz(...) {
...
foo(...);
...
}
The function foo() needs the mutex to be locked, but you want to be able to call it either from bar() where the same mutex is already locked, or from baz() where the mutex is not locked. If you used an ordinary mutex(), the thread would self-deadlock when foo() is called from bar() because the ordinary mutex lock() function will not return until the mutex is unlocked, and there's no other thread that will unlock it.
Your recursive_mutex_lock() needs to distinguish these cases; (1) The mutex is not locked, (2) the mutex is already locked, but the calling thread is the owner, and (3) the mutex is already locked by some other thread.
Case (3) needs to block the calling thread until the owner completely unlocks the mutex. At that point, it then converts to case (1). Here's a hint: Handle case (3) with a condition variable. That is to say, when the calling thread is not the owner, the calling thread should do a pthread_condition_wait(...) call.
I'm asked to write a program that will have 2 threads and print 5 random integers such that the first thread will generate a number, the second will print it. Then the first will generate the 2nd number, the second thread will print it... etc. using a mutex.
My code now execute it for one cycle. How can I extend it to make threads excute the methods 5 times?
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
void* generate (void*);
void* print (void*);
pthread_mutex_t m;
int number = 5;
int genNumber;
int main()
{
int i;
srandom(getpid());
pthread_t th[2];
pthread_mutex_init(&m,NULL);
pthread_create(&th[0],NULL,generate,NULL);
pthread_create(&th[1],NULL,print, NULL);
for (i = 0; i < 2; i++)
pthread_join(th[i], NULL);
pthread_mutex_destroy(&m);
return 0;
}
void* generate(void* arg)
{
pthread_mutex_lock(&m);
genNumber = random() % 9;
printf("Generated #1 \n");
pthread_mutex_unlock(&m);
}
void* print(void* arg)
{
pthread_mutex_lock(&m);
printf("The number is %d " , genNumber);
pthread_mutex_unlock(&m);
pthread_exit(NULL);
}
Use condition variables to synchronize the two threads. When a thread has completed its work, it signals to the other thread to wake up, and then it goes to sleep to wait for more work. So something like this:
// Pseudocode
pthread_cond_t c1, c2;
pthread_mutex_t mutex;
// Thread 1 (producer):
for(int i = 0; i < 5; i++)
{
lock(mutex);
genNumber = random() % 9;
signal(c2);
wait(c1, mutex);
unlock(mutex);
}
// Thread 2 (consumer):
for(int i = 0; i < 5; i++)
{
lock(mutex);
wait(c2, mutex);
print("The number is %d\n", genNumber);
signal(c1);
unlock(mutex);
}
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include<unistd.h>
static int *generate(void *);
static int *print(void *);
pthread_mutex_t m;
pthread_cond_t con;
int munmber=10;
int gennumber;
int main() {
srandom(getpid());
pthread_t th1,th2;
pthread_mutex_init(&m,NULL);
pthread_create(&th2,NULL,print,NULL);
sleep(1);
pthread_create(&th1,NULL,generate,NULL);
pthread_join(th1,NULL);
pthread_join(th2,NULL);
pthread_mutex_destroy(&m);
}
static int *generate(void *arg) {
int i;
while(i<5) {
pthread_mutex_lock(&m);
gennumber=random()%8;
printf("NUMMBER GENERATED.... \n");
pthread_cond_signal(&cond);
i++;
pthread_mutex_unlock(&m);
sleep(2);
if(i==5)
exit(1);
}
return 0;
}
static int *print(void *arg) {
int i;
while('a') {
pthread_cond_wait(&cond,&m);
printf("GENERATED NUMBER is %d\n",gennumber);
i++;
pthread_mutex_unlock(&m);
}
return 0;
}
A mutex is not sufficient here. You will need a condition variable to make sure that the numbers are printed in the correct order. Some pseudocode:
//producer thread:
for(int i = 0; i < 5; i++)
{
number = random();
signal the other thread with pthread_cond_signal
wait for signal from the consumer
}
// consumer thread
for(int i = 0; i < 5; i++)
{
wait for signal with pthread_cond_wait
print number
signal the producer to produce another number
}
You can do it like this:
int* generated = null;
void generate() {
int i = 0;
while (i<5) {
pthread_mutex_lock(&m);
if (generated == null) {
generated = malloc(int);
*generated = random() % 9;
printf("Generated #1 \n");
++i;
}
pthread_mutex_unlock(&m);
}
pthread_exit(NULL);
}
void print() {
int i = 0;
while (i<5) {
pthread_mutex_lock(&m);
if (generated != null) {
printf("The number is %d " , generated);
free(generated);
generated=null;
}
pthread_mutex_unlock(&m);
}
pthread_exit(NULL);
}
Actually I did write it without a compiler so there can be some errors but the concept should work.