Simulating a train with threads
c, multithreading, pthreads
Solution
The problem with your code is that all `pthread_mutex_lock(&mutex);` does is wait until `mutex` is no longer locked, and then locks it. It doesn't actually check what the value of `t` is.
What you're really looking for is a condition variable:
#include <pthread.h>
#include <stdio.h>
#include <time.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
void *train()
{
int km;
static int t = 0;
km = 1;
while (km != 30)
{
printf("I'm at %02d km\n", km);
// If we've reached the bridge, wait until less than two trains are on it.
if (km == 2)
{
pthread_mutex_lock(&mutex);
while (t == 2) { // To be read as: "While two trains are on the bridge, wait."
pthread_cond_wait(&cond, &mutex);
}
++t; // Put this train onto the bridge.
pthread_mutex_unlock(&mutex);
}
// Leave the bridge.
if (km == 4)
{
pthread_mutex_lock(&mutex);
--t; // Take this train off the bridge.
pthread_cond_signal(&cond); // Signal another train to enter.
pthread_mutex_unlock(&mutex);
}
// Move forward 1 km.
sleep(1);
++km;
}
}
int main()
{
pthread_t train1;
pthread_t train2;
pthread_t train3;
pthread_t train4;
pthread_create(&train1, NULL, train, NULL);
pthread_create(&train2, NULL, train, NULL);
pthread_create(&train3, NULL, train, NULL);
pthread_create(&train4, NULL, train, NULL);
pthread_join(train1, NULL);
pthread_join(train2, NULL);
pthread_join(train3, NULL);
pthread_join(train4, NULL);
}
The point of the extra lock and unlock in the `if (km == 4)` bit is to make sure that there aren't multiple threads trying to change/check for the value of `t` at once. (multiple threads accessing the same variable at once usually results in very buggy behaviour!)
Problem
Edit : I think i'm making somthing wrong because when I compile and run my binary twice, I get differents outputs.. I'm trying to understand threads with `pthread` so I did a little code to simulate the passage of a train on a bridge (who can handle only 2 train at a time) I managed to do it for only one train to cross the bridge at a time with a code like this : ``` #include <pthread.h> #include <stdio.h> #include <time.h> pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; void *train() { int km; static int t = 0; km = 1; while (km != 10) { printf("I'm at %02d km\n", km++); sleep(1); if (km == 2) pthread_mutex_lock(&mutex); if (km == 4) pthread_mutex_unlock(&mutex); } } int main() { pthread_t train1; pthread_t train2; pthread_t train3; pthread_create(&train1, NULL, train, NULL); pthread_create(&train2, NULL, train, NULL); pthread_create(&train3, NULL, train, NULL); pthread_join(train1, NULL); pthread_join(train2, NULL); pthread_join(train3, NULL); } ``` This one worked perfectly (Or maybe did I do something wrong, if so please tell me) And then I tried for the case when 2 train can pass on the bridge at the same time. ``` #include <pthread.h> #include <stdio.h> #include <time.h> pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; void *train() { int km; static int t = 0; km = 1; while (km != 30) { printf("I'm at %02d km\n", km++); sleep(1); if (km == 2 && t <= 2) { ++t; pthread_mutex_lock(&mutex); } if (km == 4) { t--; pthread_mutex_unlock(&mutex); } } } int main() { pthread_t train1; pthread_t train2; pthread_t train3; pthread_t train4; pthread_create(&train1, NULL, train, NULL); pthread_create(&train2, NULL, train, NULL); pthread_create(&train3, NULL, train, NULL); pthread_create(&train4, NULL, train, NULL); pthread_join(train1, NULL); pthread_join(train2, NULL); pthread_join(train3, NULL); pthread_join(train4, NULL); } ``` So I used a static int to "cap" my train to 2 on the bridge but that don't really work and I don't see why.. My 4 train are strating, then 2 go on the train, the 2 others wait, when the 2 firsts leave the bridge, only one more go on it and the last wait 'till the 3rd one leave the bridge to go.. Actually, I'd like to have the 4 train to go, 2 go on the bridge, 2 waits and when the 2 firsts leave the bridge the 2 other go on the bridge. I'm sorry it's a bit long, but needed for understanding I guess. Thanks for your help !