Output changes each time the program is run (C pthread, semaphores) - c

Below is the code, with the only the main parts.
Each time the code is run, the output changes, I assume that it is because thread 1 does not run, but I am stumped on how to fix it.
I am aiming for the i value to be added to 10 times in thread 1 and then decremented 10 times in thread 2, but I do not know why this does not happen on each run through.
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
int i = 0;
int temp = 0;
sem_t delayT;
sem_t sync;
void * thread1(void * p)
{
sem_wait(&delayT);
while(i>0)
{
sem_wait(&sync);
i--;
temp = i;
printf("Out:%d\n",i);
sem_post(&sync);
if(temp==0)
sem_wait(&delayT);
}
}
void * thread2(void * p)
{
while(i<10)
{
sem_wait(&sync);
i++;
printf("in:%d\n",i);
if(i==10)
sem_post(&delayT);
sem_post(&sync);
}
}
int main (int argc, char * argv[]) {
pthread_t t1;
pthread_t t2;
sem_init(&delayT,0,0);
sem_init(&sync,0,1);
pthread_create (&t1, NULL, thread1, NULL);
pthread_create (&t2, NULL, thread2, NULL);
pthread_join (t2, NULL);
}

I believe that you're missing a pthread_join.
you wait for the producer thread but not the consumer then the program stop before thread 1 reach the end of its countdown.
Add
pthread_join(t1, NULL);
at the end

regarding: for the i value to be added to 10 times in thread 1 and then decremented 10 times in thread 2,
the i value is NOT being added to in thread 1.
the i value is NOT being decremented in thread 2.
So, either the posted code is wrong or the description of the problem is wrong.

You have a race condition. In Thread 2:
if(i==10)
sem_post(&delayT);
sem_post(&sync);
After posting delayT, it is possible for T1 to advance; then after T2 posts sync, T1 can advance further, so that by the time T2 tests its while condition, i is less than 10. You can disentangle it further to see the valid set of outputs, but I am sure there are a lot.
Simply moving the sem_post(&delayT) outside of the loop should fix this; but you might want to consider some other approaches to this style of problem.

Related

Segmentation fault using pthreads

I am writing a program to test my understanding of condition variables. Basically, thread 0 checks if count is even, and if so, increments it. If not, then it signals thread 1 which increments the count variable. The process continues until count reaches 15. Here is my code:
#include <pthread.h>
#include <stdio.h>
#define numThreads 2
int count=0;
pthread_mutex_t count_mutex;
pthread_cond_t count_threshold_cv;
void *checkEven(void *threadId)
{ while(count<=15){
//lock the mutex
pthread_mutex_lock(&count_mutex);
printf("even_thread: thread_id=%d count=%d\n",threadId,count);
if(count%2==0){
count++;
}
else{
printf("Odd count found, signalling to odd thread\n");
pthread_cond_signal(&count_threshold_cv);
}
pthread_mutex_unlock(&count_mutex);
sleep(1);
}
}
void *checkOdd(void *threadId)
{
pthread_mutex_lock(&count_mutex); //obtain a lock
while(count<=15){
pthread_cond_wait(&count_threshold_cv, &count_mutex); //wait() relinquishes the lock
count++;
printf("odd_thread: thread_id=%d, count=%d\n",threadId,count);
}
pthread_mutex_unlock(&count_mutex);
pthread_exit(NULL);
}
int main()
{
pthread_t threads[numThreads];
int rc;
int a=0;
int b=0;
pthread_create(&threads[0], NULL, checkEven, (void *)a);
pthread_create(&threads[1], NULL, checkEven, (void *)b);
pthread_join(0,NULL);
pthread_join(1,NULL);
pthread_exit(NULL);
}
Can someone tell me why I am getting segmentation fault(core dumped) error with this? I know that this error occurs when one process tries to violate the address space of some other process, but nothing beyond this.Can someone please help? Thanks!
You're passing a zero to pthread_join as the thread you want to join:
pthread_join(0,NULL);
You wanted:
pthread_join(threads[0],NULL);
pthread_join(threads[1],NULL);
You have several other bugs though. For one thing, your checkOdd code calls pthread_cond_wait even when it's that thread's turn.
You don't seem to understand condition variables. Specifically, you seem to think that somehow the condition variable will know whether or not the thing you are waiting for has happened. It does not -- condition variables are stateless. It's your job to keep track of what you're waiting for and whether or not it has happened.

memory synchronization

I have the function display.c :
/* DO NOT EDIT THIS FILE!!! */
#include <stdio.h>
#include <unistd.h>
#include "display.h"
void display(char *str)
{
char *p;
for (p=str; *p; p++)
{
write(1, p, 1);
usleep(100);
}
}
and display.h is:
/* DO NOT EDIT THIS FILE!!! */
#ifndef __CEID_OS_DISPLAY_H__
#define __CEID_OS_DISPLAY_H__
void display(char *);
#endif
My task is to use pthreads in order to have the following output:
abcd
abcd
abcd
..
..
Note that I must not edit the file display.c or the file display.c. I have to use mutexes in order to succeed the output that is shown above.
The following block of code is my closest attempt to finally reach the result I want:
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <unistd.h>
#include <pthread.h>
#include "display.h"
pthread_t mythread1;
pthread_t mythread2;
pthread_mutex_t m1, m2;
void *ab(void *arg)
{
pthread_mutex_lock(&m1);
display("ab");
pthread_mutex_unlock(&m1);
}
void *cd(void *arg)
{
pthread_mutex_lock(&m1);
display("cd\n");
pthread_mutex_unlock(&m1);
}
int main(int argc, char *argv[])
{
pthread_mutex_init(&m1, NULL);
pthread_mutex_init(&m2, NULL);
int i;
for(i=0;i<10;i++)
{
pthread_create(&mythread1, NULL, ab, NULL);
pthread_create(&mythread2, NULL, cd, NULL);
}
pthread_join(mythread1, NULL);
pthread_join(mythread2, NULL);
pthread_mutex_destroy(&m1);
pthread_mutex_destroy(&m2);
return EXIT_SUCCESS;
}
The output of the code above is something like this:
abcd
abcd
abcd
abcd
ababcd
cd
abcd
abcd
abcd
abcd
As you can see "ab" and "cd\n" are never mixed but every time I run the code the output differs. I want to make sure that every time I run this code the output will be:
abcd
abcd
abcd
for ten times.
I am really stuck with this since I can't find any solution from the things I already know.
A mutex cannot (by itself) solve your problem. It can prevent your two threads from running concurrently, but it cannot force them to take turns.
You can do this with a condition variable in addition to the mutex, or with a pair of semaphores. Either way, the key is to maintain at all times a sense of which thread's turn it is.
Myself, I think the semaphore approach is easier to understand and code. Each semaphore is primarily associated with a different thread. That thread must lock the semaphore to proceed. When it finishes one iteration it unlocks the other semaphore to allow the other thread to proceed, and loops back to try to lock its own semaphore again (which it cannot yet do). The other thread works the same way, but with the semaphore roles reversed. Roughly, that would be:
sem_t sem1;
sem_t sem2;
// ...
void *thread1_do(void *arg) {
int result;
do {
result = sem_wait(&sem1);
// do something
result = sem_post(&sem2);
} while (!done);
}
void *thread2_do(void *arg) {
int result;
do {
result = sem_wait(&sem2);
// do something else
result = sem_post(&sem1);
} while (!done);
}
Semaphore initialization, error checking, etc. omitted for brevity.
Updated to add:
Since you now add that you must use mutexes (presumably in a non-trivial way) the next best way to go is to introduce a condition variable (to be used together with the mutex) and an ordinary shared variable to track which thread's turn it is. Each thread then waits on the condition variable to obtain the mutex, under protection of the mutex checks the shared variable to see whether it is its turn, and if so, proceeds. Roughly, that would be:
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int whose_turn = 1;
// ...
void *thread1_do(void *arg) {
int result;
result = pthread_mutex_lock(&mutex);
while (1) {
if (whose_turn == 1) {
// do something
whose_turn = 2; // it is thread 2's turn next
}
// break from the loop if finished
result = pthread_cond_broadcast(&cond);
result = pthread_cond_wait(&cond, &mutex);
}
result = pthread_mutex_unlock(&mutex);
}
void *thread1_do(void *arg) {
int result;
result = pthread_mutex_lock(&mutex);
while (1) {
if (whose_turn == 2) {
// do something else
whose_turn = 1; // it is thread 1's turn next
}
// break from the loop if finished
result = pthread_cond_broadcast(&cond);
result = pthread_cond_wait(&cond, &mutex);
}
result = pthread_mutex_unlock(&mutex);
}
Error checking is again omitted for brevity.
Note in particular that when a thread waits on a condition variable, it releases the associated mutex. It reaquires the mutex before returning from the wait. Note also that each checks at each iteration whether it is its turn to proceed. This is necessary because spurious wakeups from waiting on a condition variable are possible.
You can use a conditional variable to take turns between threads:
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int turn = 0;
void *ab(void *arg)
{
pthread_mutex_lock(&m1);
while (turn != 0)
pthread_cond_wait(&cond, &m1);
display("ab");
turn = 1;
pthread_mutex_unlock(&m1);
pthread_cond_signal(&cond);
}
void *cd(void *arg)
{
pthread_mutex_lock(&m1);
while (turn != 1)
pthread_cond_wait(&cond, &m1);
display("cd\n");
turn = 0;
pthread_mutex_unlock(&m1);
pthread_cond_signal(&cond);
}
Another problem is, you are joining with the last two pair of threads created in main() thread, which are not necessarily the ones get executed as last. If threads created early are not completed, then you are destroying the mutex m1 while it might be in use and exiting whole process.
Consider this approach to the issue:
for(i=0;i<10;i++)
{
ab();
cd();
}
This achieves your goals completely, given the shown code. The problem with your example is that you effectively prevent any synchronization and that seems to be your goal even!
Assuming that before the output, you actually want to do something useful which takes CPU time, the answer is that you will have to change the code of display(), which is simply not suitable for parallelization. Proper concurrent code is designed to work independent of other code, in particular it shouldn't compete for resources (locks) with other calls and it shouldn't rely on the order it finishes.
In summary, you can't learn much from this, it's a bad example. In order to improve the code (the one you don't want to change, but that's your problem), consider that the resource the different threads compete for is stdout. If they each wrote to their own buffer, you could create the threads, wait for them to finish and only then reorder their results for output.

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