I am trying to make race condition and fix it with mutex lock. My code is working correct which is no race condition. Should not it make race condition?
#define MAX_RESOURCES 10
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
int available_resources = 10;
void* decrease_count(void count);
void increase_count(void *count);
pthread_t thread1;
pthread_t thread2;
int main () {
int decrease = 8;
int increase = 3;
pthread_create(&thread1, NULL, decrease_count, (void*) &decrease);
pthread_create(&thread2, NULL, increase_count, (void*) &increase);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
printf("amount of resource: %d",available_resources);
return 0;
}
void* decrease_count(void *count){
available_resources -= *((int *)count);
return NULL;
}
void* increase_count(void *count){
if(available_resources + *((int *)count) <= MAX_RESOURCES) {
available_resources += *((int *)count);
return 0;
}
return NULL;
}
Well, here, you are declaring in your thread function that you are going to be passed a reference to the increment/decrement value, so you can control how many counts each thread does when it runs.
The idea is to create a mutex in main, and use it in both threads to lock the resource, before doing the increment/decrement.
#define MAX_RESOURCES 10
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
int available_resources = 10;
void* decrease_count(void *count);
void* increase_count(void *count);
pthread_t thread1;
pthread_t thread2;
pthread_mutex_t the_mutex;
int main () {
int decrease = 8;
int increase = 3;
/* create the mutex before any of the threads has access to it */
int res = pthread_mutex_init(&the_mutex, NULL);
if (res < 0) {
fprintf(stderr, "pthread_create_mutex: %s\n",
strerror(errno));
}
pthread_create(&thread1, NULL, decrease_count, &decrease);
pthread_create(&thread2, NULL, increase_count, &increase);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
printf("amount of resource: %d\n",available_resources);
return 0;
}
void* decrease_count(void *_count){
int count = *(int *)_count;
int res = pthread_mutex_lock(&the_mutex);
if (res < 0) {
fprintf(stderr, "%s: mutex lock: %s\n",
__func__,
strerror(errno));
}
available_resources -= count;
res = pthread_mutex_unlock(&the_mutex);
if (res < 0) {
fprintf(stderr, "%s: mutex unlock: %s\n",
__func__,
strerror(errno));
}
return NULL;
}
void* increase_count(void *_count){
int count = *(int *)_count;
int res = pthread_mutex_lock(&the_mutex);
int overflow = 0;
if (res < 0) {
fprintf(stderr,
"%s: mutex lock: %s\n",
__func__,
strerror(errno));
}
if(available_resources + count <= MAX_RESOURCES) {
overflow = 1;
available_resources += count;
}
res = pthread_mutex_unlock(&the_mutex);
if (res < 0) {
fprintf(stderr, "%s: mutex unlock: %s\n",
__func__,
strerror(errno));
}
if (overflow) {
printf("got over the top(%d resources)\n",
MAX_RESOURCES);
}
return NULL;
}
Related
I have a program which consists of multiple threads.
These threads have to synchronize at some point, continue together, do their work of different lengths and then synchronize again.
Here's the example of what I mean:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#define NUM_THREADS 10
void* thread(void* idp);
int threads_running = 0;
pthread_mutex_t* mutex;
pthread_cond_t* cond;
int main(int args, char **argv)
{
pthread_mutex_t mutex_var;
pthread_cond_t cond_var;
mutex = &mutex_var;
cond = &cond_var;
pthread_mutex_init(mutex, NULL);
pthread_cond_init(cond, NULL);
pthread_t threads[NUM_THREADS];
for (int i = 0; i < NUM_THREADS; i++)
{
printf("Creating Thread %d....\n", i);
int* id = malloc(sizeof(int));
*id = i;
if(0 != pthread_create(&threads[i], NULL, thread, (void *) id))
{
perror("Error while creating the threads");
exit(1);
}
}
for (int i = 0; i < NUM_THREADS; i++)
{
pthread_join(threads[i], NULL);
}
return 0;
}
void* thread(void* idp)
{
int* id = (int*) idp;
while (1)
{
sleep(*id+2); // Thread work
pthread_mutex_lock(mutex);
threads_running++;
pthread_mutex_unlock(mutex);
pthread_cond_broadcast(cond);
printf("Thread %d WAIT\n", *id);
fflush(stdout);
// Let threads synchronize
pthread_mutex_lock(mutex);
while(threads_running != NUM_THREADS)
{
pthread_cond_wait(cond, mutex);
}
pthread_mutex_unlock(mutex);
printf("Thread %d WAKEUP\n", *id);
fflush(stdout);
// and continue
pthread_mutex_lock(mutex);
threads_running--;
pthread_mutex_unlock(mutex);
}
}
The thing that happens, is that some (usually #9 and one or two others) reach Thread %d WAKEUP but before the others can wake-up threads_running is already smaller than NUM_THREADS.
How can I synchronize multiple threads, so they continue together?
I am having some trouble wrapping my head around the parallel accesses to variables.
I found the answer seconds later:
Change while(threads_running != NUM_THREADS) to while(threads_running != 0 && threads_running != NUM_THREADS)
Change threads_running--; to threads_running = 0;
Now it works perfectly.
I recommend using pthread_cond_signal() than pthread_cond_broadcast(cond);
So the code flow where while loop is exiting looks like below.
pthread_mutex_lock(mutex);
while(threads_running != 0 && threads_running != NUM_THREADS)
{
pthread_cond_wait(cond, mutex);
}
pthread_cond_signal(cond);
So the final code looks like this:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#define NUM_THREADS 10
void* thread(void* idp);
int threads_running = 0;
pthread_mutex_t* mutex;
pthread_cond_t* cond;
int main(int args, char **argv)
{
pthread_mutex_t mutex_var;
pthread_cond_t cond_var;
mutex = &mutex_var;
cond = &cond_var;
pthread_mutex_init(mutex, NULL);
pthread_cond_init(cond, NULL);
pthread_t threads[NUM_THREADS];
for (int i = 0; i < NUM_THREADS; i++)
{
printf("Creating Thread %d....\n", i);
int* id = malloc(sizeof(int));
*id = i;
if(0 != pthread_create(&threads[i], NULL, thread, (void *) id))
{
perror("Error while creating the threads");
exit(1);
}
}
for (int i = 0; i < NUM_THREADS; i++)
{
pthread_join(threads[i], NULL);
}
return 0;
}
void* thread(void* idp)
{
int* id = (int*) idp;
while (1)
{
sleep(*id+2); // Thread work
pthread_mutex_lock(mutex);
threads_running++;
pthread_mutex_unlock(mutex);
printf("Thread %d WAIT\n", *id);
fflush(stdout);
// Let threads synchronize
pthread_mutex_lock(mutex);
while(threads_running != 0 && threads_running != NUM_THREADS)
{
pthread_cond_wait(cond, mutex);
}
pthread_cond_signal(cond);
pthread_mutex_unlock(mutex);
printf("Thread %d WAKEUP\n", *id);
fflush(stdout);
// and continue
pthread_mutex_lock(mutex);
threads_running = 0;
pthread_mutex_unlock(mutex);
}
}
I am trying to understand the concept of counting semaphore through an example. But I want to implement this using SysV in Linux.
I am familiar with theoretical part of binary semaphore and counting semaphore.
I have referred this link.
Conceptually, semaphores are used as a signaling mechanism from one process to another, so I was trying to write a simple program.
In the below program, I want thread_1 to wait till it doesn't get a signal from thread_2 and similarly thread_2 should wait till it doesn't get a signal from thread_3.
So that the output should be something like this:
Hello From thread 3
Hello from thread 2
Hello from thread 1
I know it can be achieved using pthread_join() properly but I want to achieve it using semaphores.
Code:
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <errno.h>
int sem_id;
struct sembuf sops[3];
void thread_1(void)
{
sops[0].sem_num = 0;
sops[0].sem_op = 0;
sops[0].sem_flg = 0;
if(semop(sem_id, sops, 1) < 0)
perror("Semop In thread 3");
else
printf("Hello From thread 1\n");
}
void thread_2(void)
{
sops[0].sem_num = 0;
sops[0].sem_op = -1;
sops[0].sem_flg = 0;
if(semop(sem_id, sops, 1) < 0)
perror("Semop In thread 2");
else
printf("Hello from thread 2\n");
}
void thread_3(void)
{
sops[0].sem_num = 0;
sops[0].sem_op = -1;
sops[0].sem_flg = 0;
if(semop(sem_id, sops, 1) < 0)
perror("Semop In thread 3");
else
printf("Hello from thread 3\n");
}
int main(void)
{
void (*funct[]) = {thread_1, thread_2, thread_3};
key_t semkey;
char i;
union semun {
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO
(Linux-specific) */
}arg;
pthread_t thread_id[3];
semkey = ftok("/tmp", 'a');
if(semkey < 0)
perror("Cannot Create Semaphore Key");
else
{
sem_id = semget(semkey, 1, (IPC_CREAT|IPC_EXCL|0666));
if(sem_id < 0)
perror("Cannot create semaphore\n");
else
{
arg.val = 3;
if (semctl(sem_id, 0, SETVAL, arg) == -1) {
perror("semctl");
exit(1);
}
}
}
for(i = 0; i < 3; i++)
{
if(pthread_create(&thread_id[i], NULL, funct[i], NULL) < 0)
perror("Cannot Create thread\n");
}
for(i = 0; i < 3; i++)
pthread_join(thread_id[i], NULL);
if(semctl(sem_id, 0, IPC_RMID, NULL) == -1)
perror("semctl");
return 0;
}
Do I have to use more than one semaphore set to achieve what I am trying to do?
You need two mutexes / semaphores with count 1.
Assuming your threads are called t0,t1,t2 and your semaphores sem0 and sem1, then t0 runs freely and increments sem0, t1 waits on sem0 and increments sem1, and t2 waits on sem1.
Here's a complete draft without error checking:
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <errno.h>
static int sem0, sem1;
#define POST1(Sem) semop(Sem, &(struct sembuf){0,1,0}, 1)
#define WAIT1(Sem) semop(Sem, &(struct sembuf){0,-1,0}, 1)
static void* t0(void *unused) { puts("hello from t0"); POST1(sem0); return 0; }
static void* t1(void *unused) { WAIT1(sem0); puts("hello from t1"); POST1(sem1); return 0; }
static void* t2(void *unused) { WAIT1(sem1); puts("hello from t2"); return 0; }
int main(void)
{
key_t sem0_k, sem1_k;
sem0_k = ftok("/tmp", '0');
sem1_k = ftok("/tmp", '1');
sem0 = semget(sem0_k, 1, (IPC_CREAT|IPC_EXCL|0666));
sem1 = semget(sem1_k, 1, (IPC_CREAT|IPC_EXCL|0666));
pthread_t tids[3];
pthread_create(tids+2, NULL, t2, NULL);
sleep(1);
pthread_create(tids+1, NULL, t1, NULL);
sleep(1);
pthread_create(tids+0, NULL, t0, NULL);
for(int i = 0; i < 3; i++)
pthread_join(tids[i], NULL);
semctl(sem0, 0, IPC_RMID, NULL);
semctl(sem1, 0, IPC_RMID, NULL);
return 0;
}
I'm running the threads in reverse order and with 1 second waits in between t0 and t1, and t1 and t2 to show the semaphores do the job of ordering the threads from t0 to t2.
#PSkocik, based on your answer, I modified my code to use a set of two semaphores. Here is the code:
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <errno.h>
int sem_id;
struct sembuf sops;
void thread_1(void)
{
/*Wait on Set1 of Semaphore*/
sops.sem_num = 1;
sops.sem_op = -1;
sops.sem_flg = 0;
if(semop(sem_id, &sops, 1) < 0)
perror("Semop Wait In thread 3");
else
printf("Hello From thread 1\n");
}
void thread_2(void)
{
/*Wait on Set0 of Semaphore*/
sops.sem_num = 0;
sops.sem_op = -1;
sops.sem_flg = 0;
if(semop(sem_id, &sops, 1) < 0)
perror("Semop Wait In thread 2");
else
printf("Hello from thread 2\n");
/*Post on Set1 of Semaphore*/
sops.sem_num = 1;
sops.sem_op = 1;
sops.sem_flg = 0;
if(semop(sem_id, &sops, 1) < 0)
perror("Semop Post In thread 2");
}
void thread_3(void)
{
printf("Hello from thread 3\n");
/*Post operation on Set0 of semaphore*/
sops.sem_num = 0;
sops.sem_op = 1;
sops.sem_flg = 0;
if(semop(sem_id, &sops, 1) < 0)
perror("Semop In thread 3");
else
{ ; }
}
int main(void)
{
void (*funct[]) = {thread_1, thread_2, thread_3};
key_t semkey;
char i;
union semun {
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO
(Linux-specific) */
}arg;
pthread_t thread_id[3];
semkey = ftok("/tmp", 'a');
if(semkey < 0)
perror("Cannot Create Semaphore Key");
else
{
sem_id = semget(semkey, 2, (IPC_CREAT|IPC_EXCL|0666));
if(sem_id < 0)
perror("Cannot create semaphore\n");
else
{
/*arg.val = 3;
if (semctl(sem_id, 0, SETVAL, arg) == -1) {
perror("semctl");
exit(1);
}*/
}
}
for(i = 0; i < 3; i++)
{
if(pthread_create(&thread_id[i], NULL, funct[i], NULL) < 0)
perror("Cannot Create thread\n");
}
for(i = 0; i < 3; i++)
pthread_join(thread_id[i], NULL);
if(semctl(sem_id, 0, IPC_RMID, NULL) == -1)
perror("semctl");
return 0;
}
BTW, thanks a bunch for your explanation.
I have this multithreaded program with two threads and I want to convert it to a multiprocess program so that the two thread become two process and it tells which process finishes first.
Here is the mutlithreaded program:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define OUTPUTNAME "write.out"
#define OUTPUTNAME1 "fprint.out"
void *syscall_writer_function();
void *stdlibrary_writer_function();
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;
int counter = 0;
main()
{
int rc1, rc2;
pthread_t thread1, thread2;
/* Create independent threads each of which will execute functions */
if( (rc1=pthread_create( &thread1, NULL, &syscall_writer_function, NULL)) )
{
printf("Thread creation failed: %d\n", rc1);
}
if( (rc2=pthread_create( &thread2, NULL, &stdlibrary_writer_function, NULL)) )
{
printf("Thread creation failed: %d\n", rc2);
}
pthread_join( thread1, NULL);
pthread_join( thread2, NULL);
exit(EXIT_SUCCESS);
}
void *syscall_writer_function()
{
long i;
int fd;
if ((fd=open(OUTPUTNAME,O_WRONLY|O_CREAT,0644)) < 0){
fprintf(stderr,"Can't open %s. Bye.\n",OUTPUTNAME);
exit(1);
}
for (i=0; i<50000; i++) { /* write 50,000 Ys with write */
if (write(fd,"Y",1) < 1) {
fprintf(stderr,"Can't write. Bye\n");
exit(1);
}
}
pthread_mutex_lock( &mutex2 );
counter++;
printf("Syscall finished\n");
printf("Counter value: %d\n",counter);
close(fd);
pthread_mutex_unlock( &mutex2 );
}
void *stdlibrary_writer_function()
{
long i;
FILE *fp;
if ((fp=fopen(OUTPUTNAME1,"w")) == NULL) {
fprintf(stderr,"Can't open %s. Bye.\n",OUTPUTNAME1);
exit(1);
}
for (i=0; i<400000; i++) { /* write 400,000 Xs with fprintf */
if (fprintf(fp,"X") < 1) {
fprintf(stderr,"Can't write. Bye\n");
exit(1);
}
}
counter++;
printf("Stdlibrary finished\n");
printf("Counter value: %d\n",counter);
fclose(fp);
}
How to convert it to a multiprocess program in C?
I want to create two thread which output interleave like below
Thread1:1=>Ping!
Thread2:2=>Pong!
Thread1:3=>Ping!
Thread1:4=>Ping!
Thread2:5=>Pong!
Thread2:6=>Pong!
Thread1:7=>Ping!
Thread2:8=>Pong!
Thread1:9=>Ping!
..........
until 50
and my code is below
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
void* increment1(void* arg);
void* increment2(void* arg);
int count = 0;
sem_t sem;
int main() {
//variable initialize
pthread_t thread1, thread2;
int res1 = 0, res2 = 0;
int number = 0;
int i = 0;
//create semaphore
if (sem_init(&sem, 0, 1) == -1){
printf("Semaphore creation failed!!\n");
exit(EXIT_FAILURE);
}
for (i = 0; i < 25; ++i){
//create thread
res1 = pthread_create(&thread1, NULL, increment1, NULL);
if (res1 != 0) {
printf("Thread1 creation failed!!\n");
exit(EXIT_FAILURE);
}
//wait thread synchronization
pthread_join( thread1, NULL);
res2 = pthread_create(&thread2, NULL, increment2, NULL);
if (res2 != 0) {
printf("Thread2 creation failed!!\n");
exit(EXIT_FAILURE);
}
//wait thread synchronization
pthread_join( thread2, NULL);
}
exit(EXIT_SUCCESS);
}
void* increment1(void* arg) {
sem_wait(&sem);
count ++;
printf("Thread1:%d\nPing!\n",count);
fsync(fileno(stdout));
sem_post(&sem);
}
void* increment2(void* arg) {
sem_wait(&sem);
count ++;
printf("Thread2:%d\nPong!\n",count);
fsync(fileno(stdout));
sem_post(&sem);
}
But I think that what I do isn't using two thread in parallel and is wrong, what I use is sequential alternative executing two thread and it isn't not in parallel.(By using pthread_join, thread2 will execute after thread1 finish).
I try to using semaphore it seem that it cannot assure the thread execution order.
What I want to ask is
1.how to using semaphore to assure the two thread order?
2.how to pause the thread and resume it? I think that I do is create new two pthread in a loop cycle.
Thank in advance.
Add a second semaphore and initialize it to zero so that thread1 is forced to first. Then increment1 and increment2 keep signally that it is the other threads turn to go. You had some minor hangups with where joined things that you can figure out.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
void* increment1(void* arg);
void* increment2(void* arg);
int count = 0;
sem_t sem1, sem2;
int main()
{
pthread_t thread[2];
int res = 0;
int number = 0;
int i = 0;
if (sem_init(&sem1, 0, 1) == -1)
{
printf("Semaphore creation failed!!\n");
exit(EXIT_FAILURE);
}
if (sem_init(&sem2, 0, 0) == -1)
{
printf("Semaphore creation failed!!\n");
exit(EXIT_FAILURE);
}
for (i = 0; i < 25; ++i)
{
res = pthread_create(&thread[0], NULL, increment1, NULL);
if (res != 0)
{
printf("Thread creation failed!!\n");
exit(EXIT_FAILURE);
}
res = pthread_create(&thread[1], NULL, increment2, NULL);
if (res != 0)
{
printf("Thread creation failed!!\n");
exit(EXIT_FAILURE);
}
for (int j = 0; j < 2; ++j)
{
pthread_join(thread[j], NULL);
}
}
exit(EXIT_SUCCESS);
}
void* increment1(void* arg)
{
sem_wait(&sem1);
count ++;
printf("Thread1:%d Ping!\n", count);
fsync(fileno(stdout));
sem_post(&sem2);
}
void* increment2(void* arg)
{
sem_wait(&sem2);
count ++;
printf("Thread2:%d Pong!\n", count);
fsync(fileno(stdout));
sem_post(&sem1);
}
Thank for you guys, I have modified it and it seems fine.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
int count = 0;
void* increment_1(void* arg);
void* increment_2(void* arg);
sem_t sem_1, sem_2;
sem_t c_sem;
int main() {
//variable initialize
pthread_t thread1, thread2;
int res1 = 0, res2 = 0;
int number = 0;
int i = 0;
//create semaphore
if (sem_init(&c_sem, 0, 1) == -1){
printf("Semaphore creation failed!!\n");
exit(EXIT_FAILURE);
}
if (sem_init(&sem_1, 0, 1) == -1){
printf("Semaphore creation failed!!\n");
exit(EXIT_FAILURE);
}
if (sem_init(&sem_2, 0, 0) == -1){
printf("Semaphore creation failed!!\n");
exit(EXIT_FAILURE);
}
//create thread
res1 = pthread_create(&thread1, NULL, increment_1, NULL);
if (res1 != 0) {
printf("Thread1 creation failed!!\n");
exit(EXIT_FAILURE);
}
res2 = pthread_create(&thread2, NULL, increment_2, NULL);
if (res2 != 0) {
printf("Thread2 creation failed!!\n");
exit(EXIT_FAILURE);
}
//wait thread synchronization
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
exit(EXIT_SUCCESS);
}
void* increment_1(void* arg) {
while(1){
sem_wait(&sem_1);
sem_wait(&c_sem);
if(count == 50){
sem_post(&c_sem);
sem_post(&sem_2);
exit(EXIT_SUCCESS);
}
count ++;
printf("Thread1:%d->Ping!\n",count);
fsync(fileno(stdout));
sem_post(&c_sem);
sem_post(&sem_2);
}
}
void* increment_2(void* arg) {
while(1){
sem_wait(&sem_2);
sem_wait(&c_sem);
if(count == 50){
sem_post(&c_sem);
sem_post(&sem_1);
exit(EXIT_SUCCESS);
}
count ++;
printf("Thread2:%d->Pong!\n",count);
fsync(fileno(stdout));
sem_post(&c_sem);
sem_post(&sem_1);
}
}
I am trying to use pthread mutex variables and barrier to synchronize the output of my program, but it is not working the way I want it to. Each thread is seeing its final value every 20 values (coming from the for loop) which is alright but I'm trying to make them all get to the same final value (if using 5 threads, all of them should see 100 as final value, with 4 threads, 80, etc)
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
int SharedVariable =0;
void *SimpleThread(void *args)
{
int num,val,rc;
int which =(int)args;
rc = pthread_mutex_lock(&mutex1);
for(num=0; num<20; num++){
#ifdef PTHREAD_SYNC
if(random() > RAND_MAX / 2)
usleep(10);
#endif
//pthread_mutex_lock(&mutex1);
val = SharedVariable;
printf("*** thread %d sees value %d\n", which, val);
//pthread_mutex_lock(&mutex1);
SharedVariable = val+1;
pthread_mutex_unlock(&mutex1);
}
val=SharedVariable;
printf("Thread %d sees final value %d\n", which, val);
//pthread_mutex_destroy(&mutex1);
//pthread_exit((void*) 0);
//pthread_mutex_unlock(&mutex1);
}
int main (int argc, char *argv[])
{
if(atoi(argv[1]) > 0){
int num_threads = atoi(argv[1]);
//pthread_mutex_init(&mutex1, NULL);
pthread_t threads[num_threads];
int rc;
long t;
rc = pthread_mutex_lock(&mutex1);
for(t=0; t< num_threads; t++){
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, SimpleThread, (void* )t);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
//pthread_join(thread1);
}
rc= pthread_mutex_unlock(&mutex1);
}
else{
printf("ERROR: The parameter should be a valid positive number.");
exit(-1);
}
pthread_mutex_destroy(&mutex1);
pthread_exit(NULL);
}
Any suggestions or help is greatly appreciated!
Thanks in advanced!
You need to use a barrier (pthread_barrier_wait()) before checking for the final value - this ensures that no thread will proceed until all threads have reached the barrier.
In addition, you should be calling pthread_join() to wait for the threads to finish, and you only need to hold the mutex around the increment:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
pthread_barrier_t barrier1;
int SharedVariable = 0;
void *SimpleThread(void *args)
{
int num,val;
int which = (int)args;
for(num = 0; num < 20; num++) {
#ifdef PTHREAD_SYNC
if(random() > RAND_MAX / 2)
usleep(10);
#endif
pthread_mutex_lock(&mutex1);
val = SharedVariable;
printf("*** thread %d sees value %d\n", which, val);
SharedVariable = val + 1;
pthread_mutex_unlock(&mutex1);
}
pthread_barrier_wait(&barrier1);
val = SharedVariable;
printf("Thread %d sees final value %d\n", which, val);
return 0;
}
int main (int argc, char *argv[])
{
int num_threads = argc > 1 ? atoi(argv[1]) : 0;
if (num_threads > 0) {
pthread_t threads[num_threads];
int rc;
long t;
rc = pthread_barrier_init(&barrier1, NULL, num_threads);
if (rc) {
fprintf(stderr, "pthread_barrier_init: %s\n", strerror(rc));
exit(1);
}
for (t = 0; t < num_threads; t++) {
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, SimpleThread, (void* )t);
if (rc) {
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
for (t = 0; t < num_threads; t++) {
pthread_join(threads[t], NULL);
}
}
else {
printf("ERROR: The parameter should be a valid positive number.\n");
exit(-1);
}
return 0;
}
Try to move the pthread_mutext_unlock(&mutext1) out of the for loop in your SimpleThread. You lock once and unlock mutiple(20) times in your original code.
Alternatively, you could move pthread_mutex_lock(&mutext1) into the for loop, just before you read and modify your SharedVariable. In this case, each thread's add-by-one operation may not consecutive but each thread will get the correct final value.
And before you read the final value of the SharedVariable, use a barrier to wait all the threads finish their job.