Semaphore doesn't work in C. Why? - c

Firstly, I'm Italian and sorry for my bad English.
Anyway, I should do this exercise:
"Write in C a programm which generate a thread. The main shows odd number from 1 to 9, the thread shows even number from 2 to 10. Synchronize the main and the thread with semaphores"
I have written the pseudocode in this way:
//semaphores
semParent = free
semChild = busy
main
generate thread "child"
for i=1 to 9 step 2
P(semParent)
print i
V(semChild)
end for
end main
child
for i=2 to 10 step 2
P(semChild)
print i
V(semParent)
end child
And this is how I have implemented in C:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
pthread_mutex_t semParent;
pthread_mutex_t semChild = PTHREAD_MUTEX_INITIALIZER;
void* functionChild (void* arg) {
for(int i=2; i<=10; i+=2) {
pthread_mutex_lock(&semChild);
printf("CHILD: %d\n",i);
pthread_mutex_unlock(&semParent);
}
return NULL;
}
int main(void) {
pthread_t child;
pthread_create(&child, NULL, &functionChild, NULL);
pthread_mutex_init(&semParent, NULL);
for(int i=1; i<=9; i+=2) {
pthread_mutex_lock(&semParent);
printf("PARENT : %d\n",i);
pthread_mutex_unlock(&semChild);
}
pthread_join(child, NULL);
}
But the output is always different whenever I run the program.
What's wrong?
I use CygWin64 Terminal in Windows 10 64 bit.
Thanks in advance.

A pthread_mutex_t is not a semaphore (though a semaphore can be used as a mutex if you do a "V" to initialize it to "free"). The semaphore API is sem_init, sem_post and sem_wait.
By using pthread_mutex_unlock on a mutex that was locked by another thread, your program is triggering undefined behavior.

This may not be the cause of the problem you are experiencing now, but you should never use printf() in a multithreaded program. printf() writes to a buffer and doesn't always print to the screen right away. Instead you should use sprintf() and write:
char buff[20];
sprintf("PARENT: %d\n", i);
write(1, buff, strlen(buff));

I think that pthread_mutex_init(&semParent, NULL) with NULL attributes and PTHREAD_MUTEX_INITIALIZER have the same effect, which is both locks are initialised to unlocked. Your problem though does not have a critical section with the strict meaning. So a better solution whould be condition variables as #Serhio mentioned. You can also check out semaphores http://www.csc.villanova.edu/~mdamian/threads/posixsem.html which give bigger freedom and can also have the functionality of mutexes.

Related

Why do we use additional semaphore in Producer-Consumer in C

#include <stdio.h>
#include <pthread.h>
#include <semaphore>
sem_t empty, full, mutex;
#define N 10
void* producerThread(void*) {
int i = 0;
while (1) {
sem_wait(&empty);
sem_wait(&mutex);
buff[i] = rand();
i = ++i % N;
sem_post(&mutex);
sem_post(&full);
}
}
void* consumerThread(void*) {
int i = 0;
while (1) {
sem_wait(&full);
sem_wait(&mutex);
printf("%d\n", buff[i]);
i = ++i % N;
sem_post(&mutex);
sem_post(&empty);
}
}
void main() {
pthread_t producer, consumer;
sem_init(&empty, N);
sem_init(&full, 0);
sem_init(&mutex, 1);
pthread_create(&producer, NULL, &producerThread, NULL);
pthread_create(&consumer, NULL, &consumerThread, NULL);
pthread_join(producer, NULL);
pthread_join(consumer, NULL);
sem_destroy(&empty);
sem_destroy(&full);
sem_destroy(&mutex);
}
I have the following question, this code is well know Producer-Consumer problem when learning about multi-threading, but i do not understand why do we need an additional semaphore (mutex) in this case? Can't we do everything with semaphores full & empty and there will be no problems whatsoever where producer produces on the spot consumer didnt already consume or vice-versa? Afaik with mutex we are adding additional bagage on the code and this is not necessary. Can someone point to me why we need 3 semaphores instead of 2?
I've tried running this code on my computer and everything works the same with and without additional semaphore, so I do not understand why did author choose 3 semaphores in this instance?
The empty and full semaphores take values in the range [0..N), allowing the producer to run ahead of the consumer by up to N elements.
The mutex semaphore only bounces between values 0 and 1, and enforces a critical section ensuring that only one thread is touching any part of the buffer memory at a time. However, the separate computation of i on each thread and the empty/full handshake ensures there can be no data race on individual elements of buff, so that critical section is probably overkill.
You don't show the definition of buff. For a sufficiently narrow datatype (like individual bytes), some architectures may exhibit word tearing on concurrent writes to adjacent elements. However in your example only one thread is performing writes, so even in the presence of word-tearing the concurrent adjacent reads are unlikely to observe a problem.

The mutex locks a value in a function for ever

I am new in threads in c. My code has a thread that increasing a counter and occasionally(randomly) another thread reads that counter. I used mutex in this code but my code always gives me value equal to 1. Although I used pthread_mutex_unlock but it seems the value becomes lock for ever. what should I do to solve the problem?
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
#include <pthread.h>
///////////////////////////
long int count=0;
int RunFlag=0;
pthread_mutex_t mtx;
void *readfun(void *arg)
{
while (RunFlag==0)
{
pthread_mutex_lock(&mtx);
count=count+1;
pthread_mutex_unlock(&mtx);
}
}
void *printfun(void *arg)
{
int RadnTime=0;
for (int j=0;j<4;j++)
{
RadnTime=rand()%3+1;
sleep(RadnTime);
printf("The current counter after %d seconds is: ",RadnTime);
pthread_mutex_lock(&mtx);
printf("%d\n",count);
pthread_mutex_unlock(&mtx);
}
}
void main ()
{
pthread_t thread1;
pthread_t thread2;
pthread_mutex_init(&mtx, NULL);
pthread_create(&thread1,NULL,readfun,NULL);
pthread_create(&thread2,NULL,printfun,NULL);
//stop the counter
RunFlag=1;
pthread_exit(NULL);
}
You are setting RunFlag immediately after the two threads are created, so readfun barely has any time to execute. RunFlag=1; should be at the end of printfun.
As far as I know, reading from and writing to RunFlag isn't guaranteed to be atomic, so access to it should be protected as well. I don't see a problem happening here (given the values in question), but you are entering undefined behaviour territory.
Your functions don't return anything even though they are declared as returning void*. Add return NULL; to them.
Finally, the second %d should be %ld since count is a long int.
Note that
pthread_mutex_t mtx;
pthread_mutex_init(&mtx, NULL);
can be replaced with
pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
1) You also have data race as two are accessing RunFlag. So, you need to protect it with synchronization primitive (such as mutex or use a semaphore).
But you don't need the RunFlag for this purpose. Since you can use an infinite loop in readfun() thread and then simply call _exit() from printfun() thread to exit the whole process.
2) Thread functions must return a pointer to satisfy by pthread_create()'s requirement. But you thread functions don't return anything. You can add return NULL; at the end of both thread functions.
Be aware of signed integer overflow as count could potentially overflow.

C multithread program behaviour explanation

int g_ant = 0;
void *writeloop(void *arg)
{
while(g_ant < 10)
{
g_ant++;
usleep(rand()%10);
printf("%d\n", g_ant);
}
exit(0);
}
int main(void)
{
pthread_t time;
pthread_create(&time, NULL, writeloop, NULL);
writeloop(NULL);
pthread_join(time, NUL);
return 0;
}
Hi! I have four questions which I believe goes under the category race condition...? :-)
I'm trying to figure out why the printf of g_ant, on my computer, starts on 2 and continues to 10 in 90% of the cases, with an occasional 1, 3->10 output. My guess is because of the usleep which may hinder thread1 long enough to let thread2 increment and printf before thread1 reaches printf.
Wouldn't this also mess up numbers from 2->10?
I'm also struggeling to understand pthread_join's function in this program. My understanding is that it's used to wait for a thread to complete. Is it waiting for the writeloop function started by pthread_create?
Is writeloop(null) considered second thread?
g_ant++;
isn't atomic operation, which can cause undefined behaviour. You should use
pthread_mutex_lock(&mutex);
and
pthread_mutex_unlock(&mutex);
the reason why it 90% times starts at 2 is because thread time enters the function, increments g_ant and sleeps itself. OS tends to take it away from CPU and put there another thread that is not asleep, in your case that is your main thread which again increments it by 1 runs usleep. Now g_ant has value 2, thread time resumes and prints 2 and increments it to 3. Main thread gets resumed and prints the 3 and again increments it, this keeps switching that's why you see numbers from 2 -> 10 most of the time.
Hopefully it is clear enough and should answer 2. question as well.
pthread_join makes sure that other threads finish their job before your main thread quits the program.
nope it is not considered a second thread, it runs the function on the main thread.
hope it helps.
The main thread is considered another thread. The following might help you understand what's going on before you add mutexes (assuming
you have to do that next). Usually, you don't exit() the whole process
from a thread - it would never be joined in the main thread.
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int g_ant = 0;
void *writeloop(void *arg)
{
while(g_ant < 10)
{
g_ant++;
usleep( rand() % 10 );
printf("thread: %u global: %d\n", (unsigned int)pthread_self(), g_ant);
}
return NULL;
}
int main(void)
{
pthread_t t;
pthread_create(&t, NULL, writeloop, NULL);
writeloop(NULL);
pthread_join(t, NULL);
printf("Joined\n");
return 0;
}

Thread synchronizing with mutex

I have two threads. First one should write:
1
2
3
4
5
6
7
8
9
Second one should write:
am 1
am 2
am 3
am 4
am 5
am 6
am 7
am 8
am 9
This is my code:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
pthread_mutex_t mutex;
int firstCounter = 0;
int secondCounter = 0;
void *writeloop(void *arg) {
while(firstCounter < 10) {
pthread_mutex_lock(&mutex);
firstCounter++;
printf("%d\n", firstCounter);
pthread_mutex_unlock(&mutex);
}
exit(0);
}
void *readLoop(void *arg) {
while(secondCounter < 10) {
pthread_mutex_lock(&mutex);
secondCounter++;
printf("am %d\n", secondCounter);
pthread_mutex_unlock(&mutex);
}
exit(0);
}
int main(void)
{
pthread_t tid, fid;
pthread_mutex_init(&mutex, NULL);
pthread_create(&tid, NULL, writeloop, NULL);
pthread_create(&fid, NULL, readLoop, NULL);
pthread_join(tid, NULL);
pthread_join(fid, NULL);
pthread_mutex_destroy(&mutex);
return 0;
}
But its not working correctly. Sometimes the second method doesnt work, sometimes it works. Sometimes the first one work correctly, sometimes it prints:
1
2
3
4
5
6
7
Where is my mistake?
Better to use two different mutex variables to handle the two thread for read and write operation.
Since In current situation it fully depends upon the scheduling, if write thread gets schedule first then it acquire the mutex lock. So, later read thread has to wait for mutex lock until write thread released it and vice-versa.
As the commenter suggested, don't call exit() on the thread functions because that's used to terminate a process.
Might also be a good idea to call fflush(stdout) after each printf() as well to
ensure that the print buffer is flushed by the thread that last wrote to it.
Not sure why you're using a global variable in your while() loop. Probably better to use a for loop with a local variable.

Output in multi threading program

Writing my basic programs on multi threading and I m coming across several difficulties.
In the program below if I give sleep at position 1 then value of shared data being printed is always 10 while keeping sleep at position 2 the value of shared data is always 0.
Why this kind of output is coming ?
How to decide at which place we should give sleep.
Does this mean that if we are placing a sleep inside the mutex then the other thread is not being executed at all thus the shared data being 0.
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include<unistd.h>
pthread_mutex_t lock;
int shared_data = 0;
void * function(void *arg)
{
int i ;
for(i =0; i < 10; i++)
{
pthread_mutex_lock(&lock);
shared_data++;
pthread_mutex_unlock(&lock);
}
pthread_exit(NULL);
}
int main()
{
pthread_t thread;
void * exit_status;
int i;
pthread_mutex_init(&lock, NULL);
i = pthread_create(&thread, NULL, function, NULL);
for(i =0; i < 10; i++)
{
sleep(1); //POSITION 1
pthread_mutex_lock(&lock);
//sleep(1); //POSITION 2
printf("Shared data value is %d\n", shared_data);
pthread_mutex_unlock(&lock);
}
pthread_join(thread, &exit_status);
pthread_mutex_destroy(&lock);
}
When you sleep before you lock the mutex, then you're giving the other thread plenty of time to change the value of the shared variable. That's why you're seeing a value of "10" with the 'sleep' in position #1.
When you grab the mutex first, you're able to lock it fast enough that you can print out the value before the other thread has a chance to modify it. The other thread sits and blocks on the pthread_mutex_lock() call until your main thread has finished sleeping and unlocked it. At that point, the second thread finally gets to run and alter the value. That's why you're seeing a value of "0" with the 'sleep' at position #2.
This is a classic case of a race condition. On a different machine, the same code might not display "0" with the sleep call at position #2. It's entirely possible that the second thread has the opportunity to alter the value of the variable once or twice before your main thread locks the mutex. A mutex can ensure that two threads don't access the same variable at the same time, but it doesn't have any control over the order in which the two threads access it.
I had a full explanation here but ended up deleting it. This is a basic synchronization problem and you should be able to trace and identify it before tackling anything more complicated.
But I'll give you a hint: It's only the sleep() in position 1 that matters; the other one inside the lock is irrelevant as long as it doesn't change the code outside the lock.

Resources