How to make 5 threads read and write array concurrently - c++

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.

Related

A semaphore implmentation with Peterson's N process algorithm

I need feedback on my code for following statement, am I on right path?
Problem statement:
a. Implement a semaphore class that has a private int and three public methods: init, wait and signal. The wait and signal methods should behave as expected from a semaphore and must use Peterson's N process algorithm in their implementation.
b. Write a program that creates 5 threads that concurrently update the value of a shared integer and use an object of semaphore class created in part a) to ensure the correctness of the concurrent updates.
Here is my working program:
#include <iostream>
#include <pthread.h>
using namespace std;
pthread_mutex_t mid; //muted id
int shared=0; //global shared variable
class semaphore {
int counter;
public:
semaphore(){
}
void init(){
counter=1; //initialise counter 1 to get first thread access
}
void wait(){
pthread_mutex_lock(&mid); //lock the mutex here
while(1){
if(counter>0){ //check for counter value
counter--; //decrement counter
break; //break the loop
}
}
pthread_mutex_unlock(&mid); //unlock mutex here
}
void signal(){
pthread_mutex_lock(&mid); //lock the mutex here
counter++; //increment counter
pthread_mutex_unlock(&mid); //unlock mutex here
}
};
semaphore sm;
void* fun(void* id)
{
sm.wait(); //call semaphore wait
shared++; //increment shared variable
cout<<"Inside thread "<<shared<<endl;
sm.signal(); //call signal to semaphore
}
int main() {
pthread_t id[5]; //thread ids for 5 threads
sm.init();
int i;
for(i=0;i<5;i++) //create 5 threads
pthread_create(&id[i],NULL,fun,NULL);
for(i=0;i<5;i++)
pthread_join(id[i],NULL); //join 5 threads to complete their task
cout<<"Outside thread "<<shared<<endl;//final value of shared variable
return 0;
}
You need to release the mutex while spinning in the wait loop.
The test happens to work because the threads very likely run their functions start to finish before there is any context switch, and hence each one finishes before the next one even starts. So you have no contention over the semaphore. If you did, they'd get stuck with one waiter spinning with the mutex held, preventing anyone from accessing the counter and hence release the spinner.
Here's an example that works (though it may still have an initialization race that causes it to sporadically not launch correctly). It looks more complicated, mainly because it uses the gcc built-in atomic operations. These are needed whenever you have more than a single core, since each core has its own cache. Declaring the counters 'volatile' only helps with compiler optimization - for what is effectively SMP, cache consistency requires cross-processor cache invalidation, which means special processor instructions need to be used. You can try replacing them with e.g. counter++ and counter-- (and same for 'shared') - and observe how on a multi-core CPU it won't work. (For more details on the gcc atomic ops, see https://gcc.gnu.org/onlinedocs/gcc-4.8.2/gcc/_005f_005fatomic-Builtins.html)
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdint.h>
class semaphore {
pthread_mutex_t lock;
int32_t counter;
public:
semaphore() {
init();
}
void init() {
counter = 1; //initialise counter 1 to get first access
}
void spinwait() {
while (true) {
// Spin, waiting until we see a positive counter
while (__atomic_load_n(&counter, __ATOMIC_SEQ_CST) <= 0)
;
pthread_mutex_lock(&lock);
if (__atomic_load_n(&counter, __ATOMIC_SEQ_CST) <= 0) {
// Someone else stole the count from under us or it was
// a fluke - keep trying
pthread_mutex_unlock(&lock);
continue;
}
// It's ours
__atomic_fetch_add(&counter, -1, __ATOMIC_SEQ_CST);
pthread_mutex_unlock(&lock);
return;
}
}
void signal() {
pthread_mutex_lock(&lock); //lock the mutex here
__atomic_fetch_add(&counter, 1, __ATOMIC_SEQ_CST);
pthread_mutex_unlock(&lock); //unlock mutex here
}
};
enum {
NUM_TEST_THREADS = 5,
NUM_BANGS = 1000
};
// Making semaphore sm volatile would be complicated, because the
// pthread_mutex library calls don't expect volatile arguments.
int shared = 0; // Global shared variable
semaphore sm; // Semaphore protecting shared variable
volatile int num_workers = 0; // So we can wait until we have N threads
void* fun(void* id)
{
usleep(100000); // 0.1s. Encourage context switch.
const int worker = (intptr_t)id + 1;
printf("Worker %d ready\n", worker);
// Spin, waiting for all workers to be in a runnable state. These printouts
// could be out of order.
++num_workers;
while (num_workers < NUM_TEST_THREADS)
;
// Go!
// Bang on the semaphore. Odd workers increment, even decrement.
if (worker & 1) {
for (int n = 0; n < NUM_BANGS; ++n) {
sm.spinwait();
__atomic_fetch_add(&shared, 1, __ATOMIC_SEQ_CST);
sm.signal();
}
} else {
for (int n = 0; n < NUM_BANGS; ++n) {
sm.spinwait();
__atomic_fetch_add(&shared, -1, __ATOMIC_SEQ_CST);
sm.signal();
}
}
printf("Worker %d done\n", worker);
return NULL;
}
int main() {
pthread_t id[NUM_TEST_THREADS]; //thread ids
// create test worker threads
for(int i = 0; i < NUM_TEST_THREADS; i++)
pthread_create(&id[i], NULL, fun, (void*)((intptr_t)(i)));
// join threads to complete their task
for(int i = 0; i < NUM_TEST_THREADS; i++)
pthread_join(id[i], NULL);
//final value of shared variable. For an odd number of
// workers this is the loop count, NUM_BANGS
printf("Test done. Final value: %d\n", shared);
const int expected = (NUM_TEST_THREADS & 1) ? NUM_BANGS : 0;
if (shared == expected) {
puts("PASS");
} else {
printf("Value expected was: %d\nFAIL\n", expected);
}
return 0;
}

Why am i getting infinite loop for only thread # 0 after all 5 threads run for multi threading C++ dining philosophers riddle

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.

Idea Behind Recursive Mutex Lock

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.

C++ Using semaphores instead of busy waiting

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.

Thread syncronization to print 5 random numbers

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.