user1252848
user1252848

Reputation: 85

Do I need to call sleep when critical sections are in loops to avoid deadlock?

The relevant snippets of code from the two programs are below. Basically, the consumer dequeues an integer from the shared buffer and the producer enqueues an integer from the command line. Without the call to sleep at the end of the loops, deadlock occurs. That is, both processes seem to wait for the semaphore. I don't understand how this could happen and would appreciate an explanation. Also, let me know if there is a proper alternative to my 'sleep to let the other process get a chance' solution. My gut tells me that there should be, which was the main reason I decided to post this question.

Consumer:

while (get_success == 0) {
  // critical section
  sem_wait(semaphore);
  if (*top != *bottom || *empty == 0) { // not empty
    printf("Stored Integer: %d\n", buffer[*bottom]);
    *bottom = (*bottom + 1) % N;
    if (*bottom == *top)
      *empty = 1;
    get_success = 1;
  }
  sem_post(semaphore);
  // end critical section
  if (get_success == 0)
    sleep(1);
}

Producer:

while (ins_success == 0) {
  // critical section
  sem_wait(semaphore);
  if (*top != *bottom || *empty == 1) { // not full
    buffer[*top] = atoi(input);
    *empty = 0;
    *top = (*top + 1) % N;
    ins_success = 1;
  }
  sem_post(semaphore);
  // end critical section
  if (ins_success == 0)
    sleep(1);
}

Thanks!

Upvotes: 3

Views: 298

Answers (3)

bunkerdive
bunkerdive

Reputation: 2101

What you haven't defined here is the "input" portion of your code. You have to be careful implementing multi-threaded design while utilizing I/O, and you should be particularly careful about the functions that you choose to call from within your critical sections.

In this portion of code, you call atoi() in both critical sections, so I would say that you should try peeling functionality out of your critical sections, until the issue is resolved, to give you a better idea of where your code is having issues.

Upvotes: 0

Andy Ross
Andy Ross

Reputation: 12043

Broadly, any answer to a question about process synchronization involving the use of sleep() is wrong. Never do that. At best you will produce performance bugs, at worst you will see priority inversion and deadlock issues.

The code you wrote (without the sleep!) looks to me like a reasonable attempt at mutual exclusion, and it should work. If you want the other process to wake up first, you need to use two semaphores: one to "hand the cookie" in each direction.

Upvotes: 0

perreal
perreal

Reputation: 97958

If you want to force the thread/process to yield the CPU you can use sched_yield. Sleep will force calling thread to wait even if it can continue, say, after 0.2 seconds. This is not for avoiding race conditions of course, you need semaphores for synchronization.

Upvotes: 2

Related Questions