Reputation: 5239
This is a follow up to this question.
In that code, when I was not using fflush(stdout)
output was not flushed to the screen when I kept sleep(1)
.
#define S sleep(0)
void* xThread_fn(void* arg)
{
while(1)
{
S;
pthread_mutex_lock(&read_c_mutex);
if(!read_c)
{
pthread_mutex_unlock(&read_c_mutex);
printf(" X");
}
else
{
pthread_mutex_unlock(&read_c_mutex);
pthread_exit(NULL);
}
fflush(stdout); <---THIS ONE HERE
}
}
But when I keep sleep(0)
there is no need for fflush(stdout)
, the output is properly updated on stdout
. Why is this so?
Q1. Why should the presence of sleep(0)
cause any change in the way output is flushed?
If i modify the code as follows (to track execution),
#define S sleep(1)
int read_c = 0;
pthread_mutex_t read_c_mutex = PTHREAD_MUTEX_INITIALIZER;
void* inputThread_fn(void* arg)
{
printf("%p is Input\n",pthread_self());
char inputChar;
int i = 0;
while(1)
{
S;
printf("\nChecking input");
scanf("%c",&inputChar);
if(inputChar=='C' || inputChar == 'c')
{
pthread_mutex_trylock(&read_c_mutex);
printf("%p has lock %d\n",pthread_self(),i);
read_c = 1;
pthread_mutex_unlock(&read_c_mutex);
printf("%p has UNlockED %d\n",pthread_self(),i++);
printf("%p is Gone!\n",pthread_self());
fflush(stdout);
pthread_exit(NULL);
}
}
}
void* xThread_fn(void* arg)
{
int i = 0;
printf("%p is X\n",pthread_self());
while(1)
{
S;
printf("X trying for a lock\n");
pthread_mutex_trylock(&read_c_mutex);
printf("%p has lock %d\n",pthread_self(),i);
if(!read_c)
{
pthread_mutex_unlock(&read_c_mutex);
printf("%p has UNlockED %d\n",pthread_self(),i++);
printf("X\n");
fflush(stdout);
}
else
{
printf("%p is Gone!\n",pthread_self());
pthread_mutex_unlock(&read_c_mutex);
fflush(stdout);
pthread_exit(NULL);
}
}
}
void* yThread_fn(void* arg)
{
printf("%p is Y\n",pthread_self());
int i = 0;
while(1)
{
S;
printf("Y trying for a lock\n");
pthread_mutex_trylock(&read_c_mutex);
printf("%p has lock %d\n",pthread_self(),i);
if(!read_c)
{
pthread_mutex_unlock(&read_c_mutex);
printf("%p has UNlockED %d\n",pthread_self(),i++);
printf("Z\n");
fflush(stdout);
}
else
{
printf("%p is Gone!\n",pthread_self());
pthread_mutex_unlock(&read_c_mutex);
fflush(stdout);
pthread_exit(NULL);
}
}
}
a sample output is
0xb6700b70 is Input
0xb6f01b70 is Y
0xb7702b70 is X
Checking inputY trying for a lock
0xb6f01b70 has lock 0
0xb6f01b70 has UNlockED 0
Z
X trying for a lock
0xb7702b70 has lock 0
0xb7702b70 has UNlockED 0
X
Y trying for a lock
0xb6f01b70 has lock 1
0xb6f01b70 has UNlockED 1
Z
X trying for a lock
0xb7702b70 has lock 1
0xb7702b70 has UNlockED 1
X
Y trying for a lock
0xb6f01b70 has lock 2
0xb6f01b70 has UNlockED 2
Z
X trying for a lock
0xb7702b70 has lock 2
0xb7702b70 has UNlockED 2
X
Y trying for a lock
0xb6f01b70 has lock 3
0xb6f01b70 has UNlockED 3
Z
X trying for a lock
0xb7702b70 has lock 3
0xb7702b70 has UNlockED 3
X
Y trying for a lock
0xb6f01b70 has lock 4
0xb6f01b70 has UNlockED 4
Z
X trying for a lock
0xb7702b70 has lock 4
0xb7702b70 has UNlockED 4
X
c
Y trying for a lock
0xb6f01b70 has lock 5
0xb6f01b70 has UNlockED 5
Z
X trying for a lock
0xb7702b70 has lock 5
0xb7702b70 has UNlockED 5
X
0xb6700b70 has lock 0
0xb6700b70 has UNlockED 0
0xb6700b70 is Gone!
Y trying for a lock
0xb6f01b70 has lock 6
0xb6f01b70 is Gone!
X trying for a lock
0xb7702b70 has lock 6
0xb7702b70 is Gone!
Q2. I have made use of pthread_mutex_trylock()
because I wanted the code to proceed in the while loop till it acquires a lock to check the value of read_c
. The same appears to be achieved with pthread_mutex_lock();
. That confuses me more. With pthread_mutex_trylock();
too, the output always be like this? One X
followed by one Z
. Won't there be a situation where it might be like X
X
Z
X
(Provided the thread is switched by the OS and ythread tried for a lock and failed)?
Upvotes: 0
Views: 576
Reputation: 194
When sleep is called processes is context switched out (scheduled out). sleep(0) means you are not sleeping really. So process continues to execute. Printf uses stdout which is buffered. So whatever you print goes into that ouput buffer and later on flushed onto terminal(screen). When process sleeps buffer is not flushed so you do not get output unless you do explicit flush. If you do not sleep process gets a chance to do flush buffer and immediately you get output. Whenever you use any blocking calls or sleeping behavior in program you will find this behavior of printf. If you use fprintf(stderr,"your string") then it will always print irrespective of whether you sleep or not.
Upvotes: 1
Reputation: 20402
Answering the "trylock" question.
pthread_mutex_trylock
only attempts to lock the mutex. If someone else has the mutex locked, it will just return an error and keep running. Since you're not checking the return value you might touch the data that is protected by the mutex without holding the mutex.
Your code is equivalent to not having any mutexes at all.
pthread_mutex_trylock
should only be used in situations where you for some very special reason can't wait for a lock and will fall back to a different behavior when acquiring the mutex has failed. Calling it without checking the return value is always a bug.
To be perfectly correct, you should check the return value of pthread_mutex_lock
too. But you can most often get away with not doing that. You can never get away with not checking the return value of trylock.
Upvotes: 4