Reputation: 2975
I am learning Multithreading. With regard to
http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html#SCHEDULING
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
pthread_mutex_t count_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t condition_var = PTHREAD_COND_INITIALIZER;
void *functionCount1();
void *functionCount2();
int count = 0;
#define COUNT_DONE 10
#define COUNT_HALT1 3
#define COUNT_HALT2 6
main()
{
pthread_t thread1, thread2;
pthread_create( &thread1, NULL, &functionCount1, NULL);
pthread_create( &thread2, NULL, &functionCount2, NULL);
pthread_join( thread1, NULL);
pthread_join( thread2, NULL);
printf("Final count: %d\n",count);
exit(0);
}
// Write numbers 1-3 and 8-10 as permitted by functionCount2()
void *functionCount1()
{
for(;;)
{
// Lock mutex and then wait for signal to relase mutex
pthread_mutex_lock( &count_mutex );
// Wait while functionCount2() operates on count
// mutex unlocked if condition varialbe in functionCount2() signaled.
pthread_cond_wait( &condition_var, &count_mutex );
count++;
printf("Counter value functionCount1: %d\n",count);
pthread_mutex_unlock( &count_mutex );
if(count >= COUNT_DONE) return(NULL);
}
}
// Write numbers 4-7
void *functionCount2()
{
for(;;)
{
pthread_mutex_lock( &count_mutex );
if( count < COUNT_HALT1 || count > COUNT_HALT2 )
{
// Condition of if statement has been met.
// Signal to free waiting thread by freeing the mutex.
// Note: functionCount1() is now permitted to modify "count".
pthread_cond_signal( &condition_var );
}
else
{
count++;
printf("Counter value functionCount2: %d\n",count);
}
pthread_mutex_unlock( &count_mutex );
if(count >= COUNT_DONE) return(NULL);
}
}
I want to know the control flow of the code.
As pthread_cond_wait - unlocks the mutex and waits for the condition variable cond to be signaled
What I understood about the control of flow is
1) Thread One,Two are created and thread1 is passed the control (considering Single Core Processor System)
2) When it encounters pthread_cond_wait( &condition_var, &count_mutex );
in thread1
routine void *functionCount1()
- it releases the lock and goes to wait state passing control to thread2 void *functionCount1()
3) In thread2
variable count
is checked and since it satisfies count < COUNT_HALT1 || count > COUNT_HALT2
- it signals thread1
and restarts is to increment count
4) Steps 2 to 3
is repeated which displays 1-3
by thread1
5) For count 4-7
the thread2 is in action and there is no switching between thread1
and thread2
6)For count 8-10
again steps 2-3
are repeated.
I want to know whether my understanding is correct? Does thread1
goes to sleep and thread2
wakes it up ( i.e threads are switched) for count value 1-3 and 8-10
i.e switching between threads happen 5 times
?
EDIT
My main concern to ask this question is to know if thread1
will go to sleep
state when it encounters pthread_cond_wait( &condition_var, &count_mutex );
and won't be active
again unless signalled by thread2
and only then increments count
i.e. it is not going to increment 1-3
in one go rather for each increment , it has to wait for signal from thread2
only then it can proceed further
Upvotes: 0
Views: 1821
Reputation: 153899
First: get the book by Butenhof, and study it. The page you cite is incorrect in several places, and the author obviously doesn't understand threading himself.
With regards to your questions: the first thing to say is that you cannot know about the control flow of the code. That's a characteristic of threading, and on modern processors, you'll often find the threads really running in parallel, with one core executing one thread, and another core another. And within each thread, the processor may rearrange memory accesses in unexpected ways. This is why you need mutexes, for example. (You mention "considering single core processing system", but in practice, single core general purpose systems don't exist any more.)
Second, how the threads are scheduled is up to the operating
system. In your code, for example, functionCount2
could run
until completion before functionCount1
starts, which would
mean that functionCount1
would wait forever.
Third, a thread in pthread_cond_wait
may wake up spuriously.
It is an absolute rule that pthread_cond_wait
be in a loop,
which checks whatever condition you're actually waiting for.
Maybe something like:
while ( count > COUNT_HALT1 && count < COUNT_HALT2 ) {
pthread_cond_wait( &condition_var, &count_mutex );
}
Finally, at times, you're accessing count
in a section not
protected by the mutex. This is undefined behavior; all
accesses to count
must be protected. In your case, the
locking and unlocking should probably be outside the program
loop, and both threads should wait on the conditional
variable. (But it's obviously an artificial situation—in
practice, there will almost always be a producer thread and
a consumer thread.)
Upvotes: 3
Reputation: 9706
1) Threads are created. Control is not passed to thread1, it's system scheduler who decides which thread to execute. Both threads are active, both should receive processor time, but the order is not determined. There might be several context switches, you don't really control this.
2) Correct, thread1 comes to waiting state, thread2 continues working. Again, control is not passed explicitly.
3) Yes, thread2 notifies condition variable, so thread1 will awake and try to reacquire the mutex. Control does not go immediately to thread1.
In general you should understand that you can't really control which thread to execute; it's job os the system scheduler, who can put as many context switches as it wants.
UPD: With condition variables you can control the order of tasks execution within multithreading environment. So I think your understanding is more or less correct: thread1 is waiting on condition variable for signal from thread2. When signal is received thread1 continues execution (after it reacquires the mutex). But switching between threads - there might be many of them, 5 is just a theoretical minimum.
Upvotes: 1
Reputation: 5163
In the ideal world, yes, but, in practice, not quite.
You can't predict which tread takes control first. Yes, it's likely to be thread1
, but still not guaranteed. It is the first racing condition in your code.
When thread2
takes control, most likely it will finish without stopping. Regardless of how many CPUs you have. The reason is that it has no place to yield
unconditionally. The fact you release mutex
, doesn't mean any1 can get a lock on it. Its the second racing condition in your code.
So, the thread1
will print 11
, and that is the only part guaranteed.
Upvotes: 2