This discussion is archived
3 Replies Latest reply: Nov 11, 2010 11:45 AM by 796440 RSS

Using threads in a process of two or more tasks concurrently?

812709 Newbie
Currently Being Moderated
Dear,

I need to develop through a Java application in a process that allows the same process using Threads on two or more tasks can be executed concurrently. The goal is to optimize the runtime of a program.

Then, through a program, display the behavior of a producer and two consumers at runtime!

Below is the code and problem description.

Could anyone help me on this issue?

Sincerely,

Sérgio Pitta


The producer-consumer problem

Known as the problem of limited buffer. The two processes share a common buffer of fixed size. One, the producer puts information into the buffer and the other the consumer to pull off.

The problem arises when the producer wants to put a new item in the buffer, but it is already full. The solution is to put the producer to sleep and wake it up only when the consumer to remove one or more items. Likewise, if the consumer wants to remove an item from the buffer and realize that it is empty, he will sleep until the producer put something in the buffer and awake.

To keep track of the number of items in the buffer, we need a variable, "count". If the maximum number of items that may contain the buffer is N, the producer code first checks whether the value of the variable "count" is N. If the producer sleep, otherwise, the producer adds an item and increment the variable "count".

The consumer code is similar: first checks if the value of the variable "count" is 0. If so, go to sleep if not zero, removes an item and decreases the counter by one. Each case also tests whether the other should be agreed and, if so, awakens. The code for both producer and consumer, is shown in the code below:

#define N 100                     / * number of posts in the buffer * /
int count = 0,                     / * number of items in buffer * /

void producer(void)
{
int item;

while (TRUE) {                    / * number of items in buffer * /
produce_item item = ()           / * generates the next item * /
if (count == N) sleep ()           / * if the buffer is full, go to sleep * /
insert_item (item)                / * put an item in the buffer * /
count = count + 1                / * increment the count of items in buffer * /
if (count == 1) wakeup (consumer);      / * buffer empty? * /
}

}

void consumer(void)
{
int item;

while (TRUE) {                    / * repeat forever * /
if (count == 0) sleep ()           / * if the buffer is full, go to sleep * /
remove_item item = ()           / * generates the next item * /
count = count - 1                / * decrement a counter of items in buffer * /
if (count == N - 1) wakeup (producer)      / * buffer empty? * /
consume_item (item)      / * print the item * /
}
}

To express system calls such as sleep and wakeup in C, they are shown how to call library routines. They are not part of standard C library, but presumably would be available on any system that actually have those system calls. Procedures "insert_item and remove_item" which are not shown, they register themselves on the insertion and removal of the item buffer.

Now back to the race condition. It can occur because the variable "count" unfettered access. Could the following scenario occurs: the buffer is empty and the consumer just read the variable "count" to check if its value is 0. In that instant, the scheduler decides to stop running temporarily and the consumer starting to run the producer. The producer inserts an item in the buffer, increment the variable "count" and realizes that its value is now 1. Inferring the value of "count" was 0 and that the consumer should go to bed, the producer calls "wakeup" to wake up the consumer.

Unfortunately, the consumer is not logically asleep, so the signal is lost to agree. The next time the consumer to run, test the value of "count" previously read by him, shall verify that the value is 0, and sleep. Sooner or later the producer fills the whole buffer and also sleep. Both sleep forever.

The essence of the problem is that you lose sending a signal to wake up a process that (still) not sleeping. If he were not lost, everything would work. A quick solution is to modify the rules, adding context to a "bit of waiting for the signal to wake up (wakeup waiting bit)." When a signal is sent to wake up a process that is still awake, this bit is turned on. Then, when the process trying to sleep, if the bit waiting for the signal to wake up is on, it will shut down, but the process will remain awake. The bit waiting for the signal to wake up is actually a piggy bank that holds signs of waking.

Even the bit waiting for the signal to wake the nation have saved in this simple example, it is easy to think of cases with three or more cases in which a bit of waiting for the signal to wake up is insufficient. We could do another improvisation and add a second bit of waiting for the signal to wake up or maybe eight or 32 of them, but in principle, the problem still exists.

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points