Operating System Fundamentals 40 Then threadA ran and set the value turn value one second later threadB would only wake up in another four seconds to see if the variable was set. This means that our problem has been slowed down because threadB was asleep. You maybe tempted to reduce the amount of sleeping time but this means that threadB will wake up more often and use more CPU time. Abetter option would be to have threadA actually wake up threadB when it is finished.
Signals or Semaphores A
signal (or
semaphore) is a special type of variable supporting
two operations called wait and
raise (when using the term semaphore the operation names are usually
take and
give). Because the term signal is used in Unix to mean something critical has occurred (such as a crash, we will avoid using the term signal here. However, keep in mind that many books use the terms interchangeably. Semaphores can
be used in a number of ways, but the first thing that we will consider is using them for synchronization. The two operations are
1.
Take: When a thread asks to take a semaphore, either the thread is given immediate control because the semaphore is available or else it goes into a blocked state waiting for the semaphore to become available. As soon as the semaphore is made available (usually by some other thread) the requesting thread will be immediately woken up.
2.
Give: When a thread gives a semaphore it is potentially waking up another thread that is waiting. We turn back to our example of the two threads again and consider the pseudocode to get things started Create a semaphore variable called turn Make sure the semaphore turn is not available Start threadA Start threadB Now we change the thread code slightly threadA()
{
System.out.print(“Thread A
System.out.println();
Turn.give();
} threadB()
{
Turn.take();
System.out.print(“Thread B
System.out.println();
} We had changed our startup code to indicate that we need to actually create the variable called turn. We have also included an instruction to make sure that the semaphore is not actually available to start. This is very important. We want to make sure that the give instruction in threadA is the one that makes the semaphore available.
Operating System Fundamentals
41 When threadB starts it will try to take the semaphore. If the semaphore is not available, the operating system scheduler will move the thread (and possibly the process) into the blocked state. While in this blocked state, the thread (and process) will consume no CPU. When
threadA finishes its tasks, it will give the semaphore and the give operation will cause the operating system scheduler to wake up the blocked thread and make it as ready. The creation of these semaphores is very specific to each operating system, and there are often a lot of options available for dealing with very complex problems. As an example, suppose there are two threads waiting on a single semaphore. Which thread gets the semaphore when it is given You will probably have an opinion of this immediately by saying the first thread
to ask should receive it, but perhaps the second thread was actually much more important. The options provided for the semaphores can be used to control specific behavior depending on the needs of the application. Another issue that we are deferring to the section on scheduling is how long does threadB wait In our particular example we probably want to wait until threadA is finished, regardless of how long it actually takes. In some programs waiting a really longtime might not be the right answer, and often the semaphore take operations allow for an alarm clock to wake them if the semaphore is not actually given. Of course what you do
when you wake up from an alarm, rather than actually receiving the semaphore, is very specific to the problem at hand. It is impossible to suggest in this text how to properly handle the situation.
Share with your friends: