Thread synchronizing with mutex - c

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.

Related

Stop main thread until all the other threads finishes

I want to stop the main thread until all the other threads finishes running. Is there any possible way to do that using pthreads in C ? Is there any possible way to sleep the main thread?
Here is the code I used to test.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
int a = 4;
void *func(void *arg)
{
for (int i = 0; i < 5; i++)
{
sleep(1);
printf("MY TURN : %d\n", i);
}
}
void *func_2(void *arg)
{
for (int i = 0; i < 5; i++)
{
sleep(1);
printf("YOUR TURN : %d\n", i);
}
}
void turn()
{
for (int i = 0; i < 5; i++)
{
sleep(1);
printf("THEIR TURN : %d \n", i);
}
}
int main()
{
pthread_t t_id, t_id_2;
pthread_create(&t_id, NULL, func, NULL);
pthread_create(&t_id_2, NULL, func_2, NULL);
turn();
pthread_join(t_id, NULL);
pthread_join(t_id_2, NULL);
}
Output of the code
THEIR TURN : 0
YOUR TURN : 0
MY TURN : 0
MY TURN : 1
THEIR TURN : 1
YOUR TURN : 1
MY TURN : 2
THEIR TURN : 2
YOUR TURN : 2
MY TURN : 3
THEIR TURN : 3
YOUR TURN : 3
MY TURN : 4
THEIR TURN : 4
YOUR TURN : 4
I want to run the turn() (function which is in main function) after running t_id and t_id_2 threads.
What you want is actually exactly what the pthread_join function does.
From man pthread_join:
int pthread_join(pthread_t thread, void **retval);
The pthread_join() function waits for the thread specified by <thread> to terminate.
If that thread has already terminated, then pthread_join() returns immediately.
The thread specified by <thread> must be joinable.
So in your main function you can just join the threads before calling turn:
pthread_t t_id, t_id_2;
pthread_create(&t_id, NULL, func, NULL);
pthread_create(&t_id_2, NULL, func_2, NULL);
pthread_join(t_id, NULL);
pthread_join(t_id_2, NULL);
turn();
return 0;
That way turn is called after the thread functions finish their work.
The classic way to wait for a thread is join() or pthread_join(), and that means the join caller must know all the thread ids, and the thread subroutines must return (terminate).
As thread pools and multiple pass problems came into vogue, non-terminal signalling like barrier() or pthread_barrier_init()/pthread_barrier_wait() became more common. The latter is a bit like a semaphore, with a thread count but also with one 'master' thread getting a unique return. In practice, barriers are often used in pairs, one for "are we all done this pass" with the unique 'master' thread delivering the result of the pass and another barrier to hold up the rest until the result is delivered by the 'master' thread before the problem pass variables can be modified in the next pass.

Semaphore doesn't work in C. Why?

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.

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;
}

How to switch between posix threads?

Here is what I am trying to do:
Start 10 posix threads from the main thread.
Each of the 10 threads will do some operation say 100 times.
This is what I need help with.
I want to allow thread_1 to do its thing for say 10 seconds (while threads 2-10 are suspended) and then I want to allow thread 2 to do its thing while thread 1 and threads 3-10 are suspended and so on.
How would I do that? I was looking at some pthread tutorials but things seemed complicated even though what I am trying to do is quite straightforward.
Besides any discussion on whether the OP's question makes sense or not, a possible solution could be the following:
Have a signal handler installed for each thread to be scheduled. This handler is triggered on say SIGUSR1 and internally does nothing more than to invoked a call to pause().
The thread functions all start with a call to pause(), which suspends all threads immediatly after creation.
Create all threads to be schedules using pthread_create(). Stores the pthreads created into an array pthreads.
Assign the first pthread to be run (from pthread) to pthread_first.
To start scheduling call pthread_kill(pthread_first, SIGUSR2) to resume the thread to be run first (by makeing the pause() its blocking on to return). Make pthread_current become pthread_first.
To actually perform scheduling an additional thread (perhaps the main thread) loops infinitly and calls sleep(SCHEDULING_INTERVALL) and then calls pthread_kill(pthread_current, SIGUSR1) to suspend the current thread (by invoking its signal handler and with this running into pause()). Then call pthread_kill(pthread_next, SIGUSR2) to resume the next thread (by makeing the pause() its blocking on to return). Make pthreat_current become pthread_next, and pthread_next become another entry from the array pthread filled during thread creation.
But be aware:
As the threads interupted by signals and suspended by pause() might have been caught in the middle of doing some work on shared resources and stay their until resumed the chances of stepping on each other toes are quiet high.
To all others: yes, beat me ;-)
Update:
Equivalent example:
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <signal.h>
#define THREADSMAX (3)
#define SCHEDULING_INTERVALL (5) /* seconds */
void
sigusr_handler(int signo)
{
if (SIGUSR1 == signo)
{
pause();
}
}
void *
thread_function(void * pv)
{
intptr_t iThread = (intptr_t) pv;
pause();
{
int i = 0;
for (;;)
{
printf("%d: %d\n", (int) iThread, i++);
sleep(1);
}
}
pthread_exit(NULL);
}
int
main(int argc, char ** argv)
{
struct sigaction signal_action;
memset(&signal_action, 0, sizeof(signal_action));
signal_action.sa_handler = sigusr_handler;
sigemptyset(&signal_action.sa_mask);
sigaction(SIGUSR1, &signal_action, NULL);
sigaction(SIGUSR2, &signal_action, NULL);
{
pthread_t threads[THREADSMAX] =
{ 0 };
intptr_t iThread = 0;
/* create threads */
for (; iThread < THREADSMAX; ++iThread)
{
int iResult = pthread_create(&threads[iThread], NULL, thread_function,
(void *) iThread);
if (iResult)
{
errno = iResult;
perror("pthread_created()");
exit(1);
}
}
sleep(1); /* Unreliable workaround: Try to make sure all threads have started and block in "pause()". See comments on how this might be fixed nicely ... */
/* scheduling loop */
for (iThread = 0;; ++iThread)
{
if (THREADSMAX == iThread)
{
iThread = 0;
}
/* Resume current thread */
{
int iResult = pthread_kill(threads[iThread], SIGUSR2);
if (iResult)
{
errno = iResult;
perror("pthread_kill(..., SIGUSR2)");
exit(2);
}
}
sleep(SCHEDULING_INTERVALL);
/* Suspend current thread */
{
int iResult = pthread_kill(threads[iThread], SIGUSR1);
if (iResult)
{
errno = iResult;
perror("pthread_kill(..., SIGUSR1)");
exit(3);
}
}
}
}
return 0;
}
Expected output:
0: 0
0: 1
0: 2
0: 3
0: 4
1: 0
1: 1
1: 2
1: 3
1: 4
2: 0
2: 1
2: 2
2: 3
2: 4
0: 5
0: 6
0: 7
0: 8
0: 9
1: 5
1: 6
1: 7
1: 8
1: 9
2: 5
2: 6
...
POSIX Threads: Condition Variables - what's the point?
Joining and Detaching Threads:
Using sleep() and the scheduler will context switch to another process. IMO it isn't so bad solution - it is not generic since in some scenario 100ms is a lot of time and on another it is very short.
Implement by ourself condition variables or some sort of synchronizer- but it is really isn't recommended.
You have not stated your requirements well. Do the threads all operate on independent data (with no need for synchronization between them)? If so, the whole idea of trying to do your own course scheduling in 10-second units is nonsensical. Just let them all run and do their thing. Of course it would be fairly easy to achieve what you asked for using timer signals and controlling which threads have the signal blocked, but it would also be utterly useless.
If on the other hand your threads do have data dependencies between one another, then any pattern of "run for 10 seconds then transfer control to another thread" is invalid; it could lead to deadlock if the next thread cannot proceed because of a lock the first thread holds. (I suppose it's not entirely dead-lock since control will eventually return to the first thread, but the delays could grow on a very large order if there are multiple locks involved.) Instead, in this case, you should be aiming to have which thread is running controlled by the flow of data.

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