Tomer Arazy
Tomer Arazy

Reputation: 1823

Can't find the deadlock

I got this question in a job interview and for the life of me I couldn't find the answer (and they don't tell you the answer at the end since it's a written test):

int thread2_finished = 0;

void t1() {
    printf("t1 is running\n");
    while (!thread2_finished) { usleep(50); }
    printf("t2 is doing stuff\n");    
}


void t2() {
    printf("t2 is running\n");
    sleep(5);
    printf("t2 woke up\n");    
    thread2_finished = 1;
    printf("t2 finished\n");
}

What we know is that most of the times it works - but sometimes thread1 never exists (doesn't print the last message) while thread2 does print all his messages - How is that possible?

I'm guessing i'm missing something basic here but the only thing I could think about it that the problem is with the cache - like T1 loads the value (0) and cache it, then immediately T2 changes the value to 1, but for some odd reason T1 will keep using the old cached value but that seems weird to me.

Upvotes: 1

Views: 151

Answers (2)

Art
Art

Reputation: 20402

You have no guarantee that t1 has started when t2 runs. sleep is not a valid substitute for proper thread synchronization.

One could also argue that thread2_finished should be volatile. In reality that shouldn't really matter since the compiler doesn't know what usleep does and therefore can't assume that usleep won't change global variables. On the other hand, on many architectures you need to have better synchronization than just updating a global variable. On some the other thread (if running on a different cpu) might not see the updated value of the global variable for a long time, on others (if not cache coherent) it might never see it. The locking primitives in the operating system should provide enough logic to make sure that side effects from one thread are seen by other threads.

In short - even though this could work in most cases, never do this. Use proper locking, condition variables and semaphores.

Upvotes: 1

tglman
tglman

Reputation: 527

The code wrote like this seems correct (and it is in a logic way) but if you use real environment it can not work correctly, the fix will be the volatile keyword but the reason are a bit complex, also because the behavior of this keyword change every language/compiler, here the correct answer

Upvotes: 1

Related Questions