{"id":141,"date":"2018-07-19T07:30:55","date_gmt":"2018-07-19T07:30:55","guid":{"rendered":"http:\/\/csp3.epgpbooks.inflibnet.ac.in\/?post_type=chapter&#038;p=141"},"modified":"2018-08-07T10:12:08","modified_gmt":"2018-08-07T10:12:08","slug":"process-synchronization-semaphores","status":"publish","type":"chapter","link":"https:\/\/ebooks.inflibnet.ac.in\/csp3\/chapter\/process-synchronization-semaphores\/","title":{"rendered":"Process Synchronization &#8211; Semaphores"},"content":{"raw":"<div>\r\n\r\n&nbsp;\r\n<p style=\"text-align: justify\"><strong>14.1 Introduction<\/strong><\/p>\r\n&nbsp;\r\n<p style=\"text-align: justify\"><span style=\"text-align: initial;font-size: 1em\">Cooperating processes share data. Hence, the processes that access the shared data need to be synchronized so that there is no data inconsistency. In the earlier modules, we saw a number of solutions that helped in achieving process synchronization. We learned solutions for two processes as well as for multiple processes. The solutions to the critical section problem learned in the earlier modules are not easy to generalize to more complex problems. To overcome this difficulty, we can use a synchronization tool called a semaphore. The objectives of this module are as follows:<\/span><\/p>\r\n\r\n<\/div>\r\n<div style=\"text-align: justify\">\r\n\r\n&nbsp;\r\n\r\nTo understand what a semaphore is\r\n\r\nTo learn how semaphores can be used to achieve synchronization\r\n\r\nTo understand the difference between counting and binary semaphores\r\n\r\nTo learn how a counting semaphore can be implemented using binary semaphores\r\n\r\n&nbsp;\r\n\r\n<strong>14.2. Semaphores<\/strong>\r\n\r\n&nbsp;\r\n<p style=\"text-align: justify\">A semaphore is a synchronization tool that does not require busy waiting. The semaphore is an integer variable. The semaphore, being an integer variable, is assigned an initial value. The initial value denotes the number of processes that can simultaneously access the shared resource guarded by the semaphore. For example, if the shared resource can be accessed by only one process, then the initial value is set to 1. The semaphore can be accessed only via two atomic operations, namely, wait (<em>P <\/em>operation) and signal (<em>V <\/em>operation).<\/p>\r\n&nbsp;\r\n\r\nThe definition of the wait operation is given below:\r\n<p style=\"padding-left: 30px\"><em>wait <\/em>(<em>S<\/em>):<\/p>\r\n<p style=\"padding-left: 60px\">while <em>S<\/em>\u00a3 0 do <em>no-op<\/em>; <em>S<\/em>-<\/p>\r\n<p style=\"padding-left: 60px\">-;<\/p>\r\n&nbsp;\r\n<p style=\"text-align: justify\">Here S is the semaphore. Any process that wants to enter its critical section should first perform the wait operation on the semaphore. The wait operation works as follows: If the value of the semaphore is less than or equal to zero, the process waits in the while loop. If the value\u00a0of the semaphore is greater than zero, then the process comes out of the while loop and the value of the semaphore is decremented. Any process that comes out of its critical section should perform the signal operation on the semaphore.<\/p>\r\n&nbsp;\r\n\r\nThe definition of the signal operation is given below:\r\n<p style=\"padding-left: 30px\"><em>signal <\/em>(<em>S<\/em>):<\/p>\r\n<p style=\"padding-left: 90px\"><em>S++;<\/em><\/p>\r\n&nbsp;\r\n\r\nIn the signal operation, the value of the semaphore is incremented.\r\n\r\n&nbsp;\r\n<p style=\"text-align: justify\">The wait and signal operations are atomic or indivisible. Indivisibility of the wait and signal operations is ensured by the programming language or the operating system that implements it. It ensures that race conditions cannot arise over a semaphore.<\/p>\r\n\r\n<\/div>\r\n&nbsp;\r\n<p style=\"text-align: justify\"><span style=\"text-align: initial;font-size: 1em\">We \u00a0can \u00a0use \u00a0semaphores \u00a0to \u00a0deal \u00a0with \u00a0the \u00a0<\/span><em style=\"text-align: initial;font-size: 1em\">n<\/em><span style=\"text-align: initial;font-size: 1em\">-process \u00a0critical-section \u00a0problem. \u00a0The following section explains how a semaphore can be used to solve the critical-section problem.<\/span><\/p>\r\n\r\n<div style=\"text-align: justify\">\r\n\r\n&nbsp;\r\n\r\n<strong>14.2.1 Critical Section of <em>n <\/em>Processes<\/strong>\r\n\r\n&nbsp;\r\n\r\nShared data:\r\n<p style=\"padding-left: 60px\">semaphore mutex; \/\/initially <em>mutex <\/em>= 1<\/p>\r\n&nbsp;\r\n<p style=\"padding-left: 30px\">The algorithm for process <em>P<\/em>i is given below:<\/p>\r\n<p style=\"padding-left: 60px\"><span style=\"text-align: initial;font-size: 1em\">do {<\/span><\/p>\r\n<p style=\"padding-left: 90px\"><span style=\"text-align: initial;font-size: 1em\">\u00a0wait (mutex);<\/span><\/p>\r\n\r\n<\/div>\r\n<div style=\"text-align: justify;padding-left: 30px\">\r\n<p style=\"padding-left: 150px\">critical section<\/p>\r\n<p style=\"padding-left: 60px\">signal (mutex);<\/p>\r\n<p style=\"padding-left: 120px\">remainder section<\/p>\r\n\r\n<\/div>\r\n<p style=\"text-align: justify;padding-left: 30px\"><span style=\"text-align: initial;font-size: 1em\">} while (1);<\/span><\/p>\r\n\r\n<div style=\"text-align: justify\">\r\n\r\n&nbsp;\r\n<p style=\"text-align: justify\">A semaphore called \u2018mutex\u2019 is used here for guarding a shared resource. The initial value of \u2018mutex\u2019 is set to one. This means that only one process can use the shared resource at a particular time. Process <em>P<\/em>i, before entering its critical section, waits on the semaphore mutex. Process <em>P<\/em>i, after coming out of its critical section, signals the semaphore \u2018mutex\u2019.<\/p>\r\n&nbsp;\r\n<p style=\"text-align: justify\">Let us now see a sequence of execution of two processes <em>P<\/em><sub>0<\/sub> and <em>P<\/em><sub>1<\/sub>\u00a0 wanting to enter their respective critical sections.<\/p>\r\n&nbsp;\r\n\r\n<strong><em>P<\/em><\/strong><strong>0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <\/strong><strong>mutex\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <em>P<\/em><\/strong><strong>1<\/strong>\r\n\r\n1\r\n\r\nwait operation\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0\r\n\r\n<\/div>\r\n<p style=\"text-align: justify\"><span style=\"text-align: initial;font-size: 1em\">Process enters critical section\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0\u00a0wait operation\u00a0<\/span><\/p>\r\n\r\n<div style=\"text-align: justify\">\r\n\r\n\u00a0 \u00a0signal operation \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 1\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0<span style=\"text-align: initial;font-size: 1em\">Process waits<\/span>\r\n\r\n<span style=\"text-align: initial;font-size: 1em\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 0\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0Process enters<\/span>\r\n\r\n<\/div>\r\n<div style=\"text-align: justify\">\r\n\r\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 critical section\r\n\r\n1\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0signal operation\r\n\r\n&nbsp;\r\n<p style=\"text-align: justify\">Initially, process <em>P<\/em>0 wants to enter its critical section. <em>P<\/em>0 executes the wait operation on the semaphore mutex. Since the value of mutex is 1, the wait operation decrements the value of mutex. The value of mutex becomes 0. <em>P<\/em>0 enters its critical section. In the meantime, if process <em>P<\/em>1 wants to enter its critical section, it executes the wait operation. Since the value of mutex is 0, process <em>P<\/em>1 continues to wait in the while loop <strong>while <em>S<\/em><\/strong>\u00a3 <strong>0 do <em>no-op<\/em>;<\/strong>. When process <em>P<\/em>0 comes out of its critical section, it executes the signal operation on the semaphore mutex. This signal operation increments the value of mutex. The value of mutex now becomes 1. Process <em>P<\/em>1, which is checking the value of mutex in the while loop, now comes out of the while loop, decrements the value of mutex to 0 and enters its critical section.<\/p>\r\n&nbsp;\r\n<p style=\"text-align: justify\">The implementation of the wait and signal operations on a semaphore that we have seen now has a disadvantage \u2013 busy waiting. That is, when one process is in its critical section, any other process trying to enter its critical section, continuously checks the value of semaphore in the wait operation. Whenever the process waiting to enter its critical section gets the CPU, it executes <strong>while <em>S<\/em><\/strong>\u00a3 <strong>0 do <em>no-op<\/em>;. <\/strong>That is, the process just keeps on checking if <em>S <\/em>\u00a3 0. The value\u00a0<span style=\"font-size: 1em;text-align: initial\">of S is not going to change until this process relinquishes the CPU and some other process changes it. This busy waiting wastes CPU cycles in multi-programmed systems with single CPU. Such a semaphore is called a spinlock.<\/span><\/p>\r\n\r\n<\/div>\r\n<div style=\"text-align: justify\">\r\n\r\n&nbsp;\r\n<p style=\"text-align: justify\">Let us look at an example to understand spinlock. Let the initial value of semaphore S be 1. Assume that one process acquired a resource after executing a wait on the semaphore S and is continuing to use the resource. Let there be 2 other processes waiting to access the shared resource. Let round robin scheduling be the CPU scheduling algorithm. When the second process gets its CPU time slice, it will execute the while loop continuously in wait till its CPU time slice gets over. During this CPU time slice, the CPU time is used without doing any useful work. After this time slice, the third process gets its time slice. The third process also uses its entire time slice by just checking in the while loop of wait. The CPU\u2019s time is not used for any useful work. Thus it is seen that spinlock wastes CPU time.<\/p>\r\n&nbsp;\r\n<p style=\"text-align: justify\">Spinlock is useful in multiprocessor systems. The advantage of spinlock is that no context switch is required when a process must wait on a lock. This is useful when locks are for short times.<\/p>\r\n&nbsp;\r\n<p style=\"text-align: justify\">To overcome this busy waiting, the definitions of the wait and signal operations of the semaphore are modified. The semaphore is implemented as a structure or a record, rather than as just a variable. The structure has two members, an integer value and a list of processes associated with the semaphore.<\/p>\r\n&nbsp;\r\n\r\nThe semaphore is defined as follows:\r\n\r\ntypedef struct {\r\n<p style=\"padding-left: 30px\">int value;<\/p>\r\n<p style=\"padding-left: 30px\">struct process *L;<\/p>\r\n} semaphore;\r\n\r\n&nbsp;\r\n<p style=\"text-align: justify\">Two operations are defined on processes associated with the semaphore, the block and the wakeup operations. The block operation suspends the process that invokes it. The wakeup(P) operation resumes the execution of a blocked process P.<\/p>\r\n&nbsp;\r\n\r\nThe wait and signal operations on a semaphore are now defined as\r\n\r\n&nbsp;\r\n\r\n<strong><em>wait<\/em><\/strong><strong>(S):<\/strong>\r\n<p style=\"padding-left: 30px\">S.value--;<\/p>\r\n<p style=\"padding-left: 30px\">if (S.value &lt; 0)<\/p>\r\n<p style=\"padding-left: 30px\">{<\/p>\r\n<p style=\"padding-left: 90px\">add this process to S.L;<\/p>\r\n<p style=\"padding-left: 90px\">block;<\/p>\r\n<p style=\"padding-left: 30px\">}<\/p>\r\n&nbsp;\r\n<p style=\"text-align: justify\">Here S is the semaphore structure. It has an integer value (S.value) and a list of processes (S.L) associated with it. In the wait operation, the value of the semaphore is first decremented (S.value--;). Then the value of the semaphore is checked. If the value of the semaphore is less than zero, it means that the resource is not available. Therefore, the process that is executing wait is added to the list associated with the semaphore and is blocked (i.e., put to the waiting state). Compared to the earlier implementation of the wait operation, here the process does not keep on checking the value of the semaphore. Once the resource becomes available, this process is moved out of the waiting state and the process accesses the shared\u00a0<span style=\"font-size: 1em;text-align: initial\">resource.<\/span><\/p>\r\n\r\n<\/div>\r\n<div style=\"text-align: justify\">\r\n\r\n&nbsp;\r\n\r\n<strong><em>signal(S<\/em><\/strong><strong>):<\/strong>\r\n<p style=\"padding-left: 30px\">S.value++;<\/p>\r\n<p style=\"padding-left: 30px\">if (S.value &lt;= 0)<\/p>\r\n<p style=\"padding-left: 30px\">{<\/p>\r\n<p style=\"padding-left: 60px\">remove a process P from S.L;<\/p>\r\n<p style=\"padding-left: 60px\">wakeup(P);<\/p>\r\n<p style=\"padding-left: 30px\">}<\/p>\r\n&nbsp;\r\n<p style=\"text-align: justify\">In the signal operation, the value of the semaphore is incremented. This means that one more process can access the resource. Then the value of the semaphore is checked. If the value of the semaphore is less than or equal to zero, one of the waiting processes is woken up. The process that is woken up is moved to the ready state and can access the resource.<\/p>\r\n&nbsp;\r\n<p style=\"text-align: justify\">The value of the semaphore is less than or equal to zero only if there are other processes waiting in the list associated with this semaphore. (The value had become less than zero when other processes had decremented the value of the semaphore earlier while executing wait).<\/p>\r\n&nbsp;\r\n\r\n<strong>14.3\u00a0 Semaphore as a General Synchronization Tool\u00a0<\/strong>\r\n\r\n&nbsp;\r\n<p style=\"text-align: justify\">In this section, we see how the semaphore can be used as a synchronization tool. There are two processes <em>P<\/em>i and <em>P<\/em>j that want to access a common resource. Let <em>flag <\/em>be the semaphore that guards the shared resource. The shared resource can be used by only one process at a time. Therefore, the value of the semaphore <em>flag <\/em>is initialized to 1.<\/p>\r\n&nbsp;\r\n\r\n<strong><em>P<\/em><\/strong><strong>i\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <\/strong><strong>Semaphore\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <em>P<\/em><\/strong><strong>j<\/strong>\r\n\r\n<span style=\"text-align: initial;font-size: 1em\">flag = 1<\/span>\r\n\r\n<span style=\"text-align: initial;font-size: 1em\">wait(flag)\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0<\/span>\r\n\r\n<span style=\"text-align: initial;font-size: 1em\">access resource\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0\u00a0\u00a0flag = 0<\/span>\r\n\r\n&nbsp;\r\n\r\n<span style=\"text-align: initial;font-size: 1em\">signal(flag)\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0\u00a0<\/span>\r\n\r\n<\/div>\r\n<div style=\"text-align: justify\">\r\n\r\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0<span style=\"text-align: initial;font-size: 1em\">flag = -1\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0wait(flag)<\/span>\r\n\r\nflag = 0\r\n\r\naccess resource\u00a0signal(flag)\r\n\r\nflag = 1\r\n\r\n<\/div>\r\n<div style=\"text-align: justify\">\r\n\r\n&nbsp;\r\n<p style=\"text-align: justify\">Process <em>P<\/em>i executes the wait operation on the semaphore. The wait operation decrements the value of the semaphore <em>flag<\/em>. <em>flag <\/em>becomes zero. Since the value of <em>flag <\/em>is not less than zero, <em>P<\/em>i can access the resource. In the meantime, if <em>P<\/em>j wants to access the resource, <em>P<\/em>j executes the wait operation on the semaphore <em>flag<\/em>. <em>flag <\/em>is decremented and becomes -1. Since the value of <em>flag <\/em>is &lt; 0, <em>P<\/em>j is added to the list associated with the semaphore and is put to the waiting state.<\/p>\r\n&nbsp;\r\n<p style=\"text-align: justify\">When process <em>P<\/em>i completes the usage of the resource, it executes the signal operation on <em>flag<\/em>. The value of <em>flag <\/em>is incremented and becomes 0. Process <em>P<\/em>j is woken up from the sleeping state. Process <em>P<\/em>j now can access the resource. After <em>P<\/em>j completes using the resource,\u00a0<em style=\"font-size: 1em;text-align: initial\">P<\/em><span style=\"font-size: 1em;text-align: initial\">j executes the signal operation and the value of <\/span><em style=\"font-size: 1em;text-align: initial\">flag <\/em><span style=\"font-size: 1em;text-align: initial\">is incremented back to 1.<\/span><\/p>\r\n\r\n<\/div>\r\n<div style=\"text-align: justify\">\r\n\r\n&nbsp;\r\n\r\nIn this way, a semaphore can be used for safeguarding resources.\r\n\r\n&nbsp;\r\n\r\n<strong>14.4\u00a0 Deadlock and Starvation\u00a0<\/strong>\r\n\r\n&nbsp;\r\n<p style=\"text-align: justify\">When semaphores are used for synchronization, it is possible to have deadlocks and starvation. Deadlock is a situation where two or more processes are waiting indefinitely for an event that can be caused by only one of the waiting processes. For example, when two or more processes are waiting for the release of some resource that is held by another waiting process, it is a deadlock. Every process in a set of processes will be waiting for an event caused by one of the processes in the set. Starvation means indefinite blocking. A process may never be removed from the semaphore queue in which it is suspended and it starves.<\/p>\r\n&nbsp;\r\n<p style=\"text-align: justify\">Let us now see how deadlocks and starvation can happen with semaphores. Let <em>S <\/em>and <em>Q <\/em>be two semaphores initialized to 1. That is, semaphore <em>S <\/em>is safeguarding a resource that can be accessed by only one process at a time. Similarly, semaphore <em>Q <\/em>is also safeguarding another resource that can be accessed by only one process at a time.<\/p>\r\n<p style=\"padding-left: 180px\"><em>P<\/em><sub>0<\/sub>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <em>P<\/em><sub>1<\/sub><\/p>\r\n<p style=\"padding-left: 180px\"><em>wait<\/em>(<em>S<\/em>);\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <em>wait<\/em>(<em>Q<\/em>);<\/p>\r\n<p style=\"padding-left: 180px\"><em>wait<\/em>(<em>Q<\/em>);\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <em>wait<\/em>(<em>S<\/em>);<\/p>\r\n<p style=\"padding-left: 180px\">\u00a0 \u00a0 :\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 :<\/p>\r\n<p style=\"padding-left: 180px\"><em>signal<\/em>(<em>S<\/em>);\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <em>signal<\/em>(<em>Q<\/em>);<\/p>\r\n<p style=\"padding-left: 180px\"><em>signal<\/em>(<em>Q<\/em>)\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <em>signal<\/em>(<em>S<\/em>);<\/p>\r\n&nbsp;\r\n<p style=\"text-align: justify\">Consider two processes <em>P<\/em>0 and <em>P<\/em>1. <em>P<\/em>0 executes wait(S) and at the same time, <em>P<\/em>1 executes wait(Q). The values of the semaphores S and Q become 0. <em>P<\/em>0 then executes wait(Q) and waits till semaphore Q is signaled. <em>P<\/em>1 then executes wait(S) and waits till the semaphore S is signaled. Here, we see that process <em>P<\/em>0 is waiting for a resource held by <em>P<\/em>1 and process <em>P<\/em>1 is held by a resource held by <em>P<\/em>0. Each of the two processes is waiting for a resource held by the other process. Therefore, both are unable to proceed. Both the processes wait indefinitely. Both the processes are caught in a deadlock and are starving.<\/p>\r\n&nbsp;\r\n<p style=\"text-align: justify\">Therefore, the order in which wait and signal are used in processes should be selected carefully. Else, it may result in deadlocks and starvation also.<\/p>\r\n&nbsp;\r\n<p style=\"text-align: justify\">Starvation is indefinite blocking. Starvation can also happen when processes that are added to the semaphore queue are removed in a last in first out manner. That is, whenever processes wait for a resource guarded by a semaphore, the processes are added to the queue associated with the semaphore. When more processes wait for the same resource, all these processes are also added to the end of the semaphore\u2019s queue. While removing processes from the queue, if the processes are removed from the end, the processes that were added first will starve.<\/p>\r\n&nbsp;\r\n\r\n<strong>14.5\u00a0 \u00a0Types of Semaphores\u00a0<\/strong>\r\n\r\n&nbsp;\r\n<p style=\"text-align: justify\">There are two types of semaphores\u2014counting semaphores and binary semaphores. A counting semaphore takes an integer value that can range over an unrestricted domain. The semaphores that we discussed in the previous sections are counting semaphores. They are called counting semaphores because the value of the semaphores can be any integer value. A binary semaphore takes an integer value that can range only between 0 and 1. Hence, a binary\u00a0<span style=\"text-align: initial;font-size: 1em\">semaphore can be simpler to implement than counting semaphores. If we have the implementation of binary semaphores, we can implement\u00a0 counting semaphores using the implementation of binary semaphores.<\/span><\/p>\r\n\r\n<\/div>\r\n<div style=\"text-align: justify\">\r\n\r\n&nbsp;\r\n<p style=\"text-align: justify\">We now see how a counting semaphore <em>S <\/em>can be implemented using binary semaphores. S1 and S2 are the binary semaphores using which the counting semaphore S is implemented. C is an ordinary variable and the initial value of C is set to the initial value of the counting\u00a0semaphore S. The initial value of the counting semaphore S indicates the number of processes that can access the resource guarded by the semaphore S at the same time.<\/p>\r\n&nbsp;\r\n\r\n<strong>Data structures:<\/strong>\r\n<p style=\"padding-left: 60px\">binary-semaphore S1, S2;<\/p>\r\n<p style=\"padding-left: 60px\">int C;<\/p>\r\n&nbsp;\r\n<p style=\"padding-left: 30px\">S1 and S2 are two binary semaphores and C is an integer variable.<\/p>\r\n&nbsp;\r\n\r\n<strong><span style=\"text-align: justify;font-size: 1em\">Initialization:<\/span><\/strong>\r\n\r\n<\/div>\r\n<div style=\"text-align: justify;padding-left: 90px\"><span style=\"text-align: initial;font-size: 1em\">S1 = 1<\/span><\/div>\r\n<div style=\"text-align: justify;padding-left: 90px\"><span style=\"text-align: initial;font-size: 1em\">S2 = 0<\/span><\/div>\r\n<div style=\"text-align: justify;padding-left: 90px\"><span style=\"text-align: initial;font-size: 1em\">C = initial value of semaphore S<\/span><\/div>\r\n<p style=\"text-align: justify;padding-left: 60px\"><span style=\"text-align: initial;font-size: 1em\">C is assigned the initial value of the counting semaphore S. The initial values of S1 and S2 are assigned 1 and 0 respectively.<\/span><\/p>\r\n\r\n<div style=\"text-align: justify\">\r\n\r\n&nbsp;\r\n\r\n<strong>Wait and signal operations for binary semaphore:\u00a0<\/strong>\r\n\r\n<\/div>\r\n<div style=\"text-align: justify\">\r\n\r\n&nbsp;\r\n\r\nIf S1 is a binary semaphore, then the wait operation on the binary semaphore is given\u00a0below:\r\n\r\n&nbsp;\r\n\r\nwait(S1)\r\n\r\n{\r\n\r\n<\/div>\r\n<p style=\"text-align: justify;padding-left: 60px\"><span style=\"text-align: initial;font-size: 1em\">while(S1==0)<\/span><\/p>\r\n<p style=\"text-align: justify;padding-left: 60px\"><span style=\"text-align: initial;font-size: 1em\">; S1--;<\/span><\/p>\r\n\r\n<div style=\"text-align: justify\">\r\n<p style=\"padding-left: 30px\">}<\/p>\r\n&nbsp;\r\n\r\nIf the value of the binary semaphore is zero, the process that executes the wait operation, waits in the while loop. If the value is not equal to zero, the process comes out of the while loop and decrements the value of the semaphore.\r\n\r\n&nbsp;\r\n\r\nsignal(S1)\r\n\r\n{\r\n<p style=\"padding-left: 30px\">S1++;<\/p>\r\n}\r\n\r\n&nbsp;\r\n\r\nIn the signal operation, the value of the binary semaphore is incremented.\r\n\r\n&nbsp;\r\n\r\nThe wait and signal operations of the counting semaphore are given below:\r\n\r\n&nbsp;\r\n\r\n<strong><em>wait <\/em><\/strong><strong>operation<\/strong>\r\n\r\nThe wait operation on the counting semaphore can be implemented using wait and signal operations on the binary semaphore as given below:\r\n\r\n&nbsp;\r\n\r\nwait(S1);\r\n\r\nC--;\r\n\r\nif (C &lt; 0) {\r\n<p style=\"padding-left: 30px\"><span style=\"text-align: initial;font-size: 1em\">signal(S1);<\/span><\/p>\r\n<p style=\"padding-left: 30px\"><span style=\"text-align: initial;font-size: 1em\">wait(S2);<\/span><\/p>\r\n<span style=\"text-align: initial;font-size: 1em\">}<\/span>\r\n\r\n<span style=\"text-align: initial;font-size: 1em\">signal(S1);\u00a0<\/span>\r\n\r\n<\/div>\r\n<div style=\"text-align: justify\">\r\n\r\n&nbsp;\r\n<p style=\"text-align: justify\">The initial value of S1 is 1. Therefore, the wait operation on S1, finds that the value of S1 is not zero and decrements the value of S1. Next, the value of C is decremented. The initial value of C is equal to the value of the counting semaphore S. If the value of C becomes less than zero, then the process executing wait cannot proceed to execute its critical section. It has to wait. Therefore, the process signals S1 semaphore; the value of S1 becomes 1. Then, it waits on semaphore S2. Since the initial value of S2 is 0, the process waits on S2. If the value of C is not less than 0, it means that the process can enter its critical section. In this case, the process signals S1 and proceeds to enter its critical section. Here, we can see that the semaphore S1 guards the decrement of the variable C. The process waits on S1 before decrementing C and signals S1 after decrementing C. Semaphore S2 guards the shared resource.<\/p>\r\n&nbsp;\r\n\r\n<strong><em>signal <\/em><\/strong><strong>operation<\/strong>\r\n\r\n&nbsp;\r\n<p style=\"text-align: justify\">The signal operation on S is also implemented using wait and signal operations on S1 and S2. The implementation of signal(S) is given below:<\/p>\r\n&nbsp;\r\n\r\nwait(S1);\r\n\r\nC ++;\r\n\r\nif (C &lt;= 0)\r\n<p style=\"padding-left: 30px\">signal(S2);<\/p>\r\n<span style=\"text-align: initial;font-size: 1em\">else<\/span>\r\n<p style=\"padding-left: 30px\"><span style=\"text-align: initial;font-size: 1em\">signal(S1);<\/span><\/p>\r\n\r\n<\/div>\r\n<div style=\"text-align: justify\">\r\n\r\n&nbsp;\r\n<p style=\"text-align: justify\">The executing process first waits on S1. If no other process is currently incrementing or decrementing C, the value of S1 will be 1. wait(S1) decrements the value of S1 to 0. Then, C is incremented. If the value of C becomes less than or equal to zero, then it means that there is(are) other process(es) waiting to use the shared resource. In that case, signal(S2) is executed. As mentioned earlier, S2 is the semaphore that guards the shared resource. When signal(S2) is executed, another process waiting on S2 will come out of waiting, signal S1 (this is the signal(S1) in the wait operation) and proceed\u00a0 to use the shared\u00a0 resource. If C &gt; 0, signal(S1) (in the signal operation) is executed.<\/p>\r\n&nbsp;\r\n\r\nLet us see with an example, how a counting semaphore is implemented using binary semaphores. Let C = 2 (initial value of semaphore S). Since the value of semaphore S is 2, two processes can use the shared resource at the same time. Let us see what happens when three processes want to use the shared resource at the same time.\r\n\r\n&nbsp;\r\n\r\nWhen wait(S) is executed by the first process, say <em>P<\/em><sub>0<\/sub>\r\n\r\n&nbsp;\r\n\r\n<strong>wait(S) by <em>P<\/em><sub>0<\/sub>:\u00a0<\/strong>\r\n\r\n&nbsp;\r\n\r\n<strong>S<\/strong><strong>1\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0C\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 S2<\/strong>\r\n\r\n1\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 2\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0\r\n\r\n0\r\n\r\n1\r\n\r\n1\r\n\r\n<\/div>\r\n&nbsp;\r\n<p style=\"text-align: justify\"><span style=\"text-align: initial;font-size: 1em\">Initially, S1 is 0, C is 2 and S2 is 0. wait(S1) decrements the value of S1 to 0. Then C is decremented from 2 to 1. signal(S1) increments the value of S1 back to 1. <\/span><em style=\"text-align: initial;font-size: 1em\">P<\/em><span style=\"text-align: initial;font-size: 1em\">0 gets access to the shared resource.<\/span><\/p>\r\n\r\n<div style=\"text-align: justify\">\r\n\r\n&nbsp;\r\n\r\nIn the meantime, suppose process <em>P<\/em>1 \u00a0wants to access the shared resource. The sequence is shown below:\r\n\r\n&nbsp;\r\n\r\n<strong>wait(S) by <em>P<\/em><sub>1<\/sub>:\u00a0<\/strong>\r\n\r\n&nbsp;\r\n\r\n<strong>S<\/strong><strong>1\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0C\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 S2<\/strong>\r\n\r\n1\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 1\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0\r\n\r\n0\r\n\r\n0\r\n\r\n1\r\n\r\n&nbsp;\r\n<p style=\"text-align: justify\">wait(S1) decrements the value of S1 from 1 to 0.Then C is decremented from 1 to 0. signal(S1) increments the value of S1 back to 1. <em>P<\/em>1 gets access to the shared resource.<\/p>\r\n&nbsp;\r\n<p style=\"text-align: justify\">In the meantime, suppose the third process <em>P<\/em>2 \u00a0wants to access the shared resource. The sequence is shown below:<\/p>\r\n&nbsp;\r\n\r\n<strong>wait(S) by <em>P<\/em><sub>2<\/sub>:\u00a0<\/strong>\r\n\r\n&nbsp;\r\n\r\n<strong>S<\/strong><strong>1\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0C\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 S2<\/strong>\r\n\r\n1\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0\r\n\r\n0\r\n\r\n-1\r\n\r\n1\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Process <em>P<\/em>2 waits on S2\r\n\r\n&nbsp;\r\n<p style=\"text-align: justify\">wait(S1) decrements the value of S1 from 1 to 0.Then C is decremented from 0 to -1. Since the value of C goes below 0, process <em>P<\/em>2 executes wait(S2). <em>P<\/em>2 does not get access to the shared resource. Since the initial value of the semaphore S was 2, only two processes are able to access the shared resource. The other processes wait.<\/p>\r\n&nbsp;\r\n\r\nLet <em>P<\/em>0 complete the usage of the shared resource. <em>P<\/em>0 executes signal(S). The changes in the semaphores\u2019 values are shown below:\r\n\r\n&nbsp;\r\n\r\n<strong>When signal(S) is executed by <em>P<\/em><sub>0<\/sub>:\u00a0<\/strong>\r\n\r\n&nbsp;\r\n\r\n<strong>S<\/strong><strong>1\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 C\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 S2<\/strong>\r\n\r\n1\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 -1\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0\r\n\r\n0\r\n\r\n<span style=\"text-align: initial;font-size: 1em\">0<\/span>\r\n\r\n<span style=\"text-align: initial;font-size: 1em\">Released process <\/span><em style=\"text-align: initial;font-size: 1em\">P<\/em><sub style=\"text-align: justify\"><span style=\"text-align: initial\">2\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <\/span><\/sub><span style=\"text-align: initial\">1<\/span>\r\n\r\n<span style=\"text-align: initial;font-size: 1em\">signals S1 1\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0<\/span><span style=\"text-align: initial;font-size: 1em\">Process <\/span><em style=\"text-align: initial;font-size: 1em\">P<\/em><span style=\"text-align: initial;font-size: 1em\">2 \u00a0waiting on S2 is released<\/span>\r\n\r\n<\/div>\r\n&nbsp;\r\n<p style=\"text-align: justify\">wait(S1) in the signal operation decrements the value of S1 from 1 to 0.Then C is incremented from \u20131 to 0. Since the value of C becomes 0, signal(S2) is executed. Process <em>P<\/em>2 waiting on S2 is released. Process <em>P<\/em>2 signals S1 (signal(S1) in the wait operation) and gains access to the shared resource.<\/p>\r\n&nbsp;\r\n<p style=\"text-align: justify\"><strong>When signal(S) is executed by <em>P<\/em><sub>1<\/sub>:<\/strong><\/p>\r\n&nbsp;\r\n<p style=\"text-align: justify\"><strong>S<\/strong><strong>1\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0C\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 S2<\/strong><\/p>\r\n<p style=\"text-align: justify\">1\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0<\/p>\r\n<p style=\"text-align: justify\">0<\/p>\r\n<p style=\"text-align: justify\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 1<\/p>\r\n<p style=\"text-align: justify\">1<\/p>\r\n<p style=\"text-align: justify\">wait(S1) in the signal operation\u00a0 decrements the value of S1 from 1 to 0.\u00a0 Then C is incremented from 0 to 1. Since the value of C becomes greater than 0, signal(S1) is executed. The value of S1 is changed from 0 to 1. Thus, we see that a counting semaphore can be implemented using binary semaphores.<\/p>\r\n&nbsp;\r\n<p style=\"text-align: justify\"><strong>14.6\u00a0 \u00a0Summary<\/strong><\/p>\r\n&nbsp;\r\n<p style=\"text-align: justify\">In this module, we learnt how a semaphore can be used as a synchronization tool. We understood that there are two types of semaphores \u2013 counting and binary semaphores. We also learnt how a counting semaphore is implemented using binary semaphores.<\/p>\r\n&nbsp;\r\n\r\n&nbsp;\r\n<p style=\"text-align: justify\"><strong>References<\/strong><\/p>\r\n\r\n<ol>\r\n \t<li style=\"text-align: justify\">Abraham Silberschatz, Peter B. Galvin, Greg Gagne, \u201cOperating System Concepts\u201d, Ninth Edition, John Wiley &amp; Sons Inc., 2012.<\/li>\r\n<\/ol>","rendered":"<div>\n<p>&nbsp;<\/p>\n<p style=\"text-align: justify\"><strong>14.1 Introduction<\/strong><\/p>\n<p>&nbsp;<\/p>\n<p style=\"text-align: justify\"><span style=\"text-align: initial;font-size: 1em\">Cooperating processes share data. Hence, the processes that access the shared data need to be synchronized so that there is no data inconsistency. In the earlier modules, we saw a number of solutions that helped in achieving process synchronization. We learned solutions for two processes as well as for multiple processes. The solutions to the critical section problem learned in the earlier modules are not easy to generalize to more complex problems. To overcome this difficulty, we can use a synchronization tool called a semaphore. The objectives of this module are as follows:<\/span><\/p>\n<\/div>\n<div style=\"text-align: justify\">\n<p>&nbsp;<\/p>\n<p>To understand what a semaphore is<\/p>\n<p>To learn how semaphores can be used to achieve synchronization<\/p>\n<p>To understand the difference between counting and binary semaphores<\/p>\n<p>To learn how a counting semaphore can be implemented using binary semaphores<\/p>\n<p>&nbsp;<\/p>\n<p><strong>14.2. Semaphores<\/strong><\/p>\n<p>&nbsp;<\/p>\n<p style=\"text-align: justify\">A semaphore is a synchronization tool that does not require busy waiting. The semaphore is an integer variable. The semaphore, being an integer variable, is assigned an initial value. The initial value denotes the number of processes that can simultaneously access the shared resource guarded by the semaphore. For example, if the shared resource can be accessed by only one process, then the initial value is set to 1. The semaphore can be accessed only via two atomic operations, namely, wait (<em>P <\/em>operation) and signal (<em>V <\/em>operation).<\/p>\n<p>&nbsp;<\/p>\n<p>The definition of the wait operation is given below:<\/p>\n<p style=\"padding-left: 30px\"><em>wait <\/em>(<em>S<\/em>):<\/p>\n<p style=\"padding-left: 60px\">while <em>S<\/em>\u00a3 0 do <em>no-op<\/em>; <em>S<\/em>&#8211;<\/p>\n<p style=\"padding-left: 60px\">-;<\/p>\n<p>&nbsp;<\/p>\n<p style=\"text-align: justify\">Here S is the semaphore. Any process that wants to enter its critical section should first perform the wait operation on the semaphore. The wait operation works as follows: If the value of the semaphore is less than or equal to zero, the process waits in the while loop. If the value\u00a0of the semaphore is greater than zero, then the process comes out of the while loop and the value of the semaphore is decremented. Any process that comes out of its critical section should perform the signal operation on the semaphore.<\/p>\n<p>&nbsp;<\/p>\n<p>The definition of the signal operation is given below:<\/p>\n<p style=\"padding-left: 30px\"><em>signal <\/em>(<em>S<\/em>):<\/p>\n<p style=\"padding-left: 90px\"><em>S++;<\/em><\/p>\n<p>&nbsp;<\/p>\n<p>In the signal operation, the value of the semaphore is incremented.<\/p>\n<p>&nbsp;<\/p>\n<p style=\"text-align: justify\">The wait and signal operations are atomic or indivisible. Indivisibility of the wait and signal operations is ensured by the programming language or the operating system that implements it. It ensures that race conditions cannot arise over a semaphore.<\/p>\n<\/div>\n<p>&nbsp;<\/p>\n<p style=\"text-align: justify\"><span style=\"text-align: initial;font-size: 1em\">We \u00a0can \u00a0use \u00a0semaphores \u00a0to \u00a0deal \u00a0with \u00a0the \u00a0<\/span><em style=\"text-align: initial;font-size: 1em\">n<\/em><span style=\"text-align: initial;font-size: 1em\">-process \u00a0critical-section \u00a0problem. \u00a0The following section explains how a semaphore can be used to solve the critical-section problem.<\/span><\/p>\n<div style=\"text-align: justify\">\n<p>&nbsp;<\/p>\n<p><strong>14.2.1 Critical Section of <em>n <\/em>Processes<\/strong><\/p>\n<p>&nbsp;<\/p>\n<p>Shared data:<\/p>\n<p style=\"padding-left: 60px\">semaphore mutex; \/\/initially <em>mutex <\/em>= 1<\/p>\n<p>&nbsp;<\/p>\n<p style=\"padding-left: 30px\">The algorithm for process <em>P<\/em>i is given below:<\/p>\n<p style=\"padding-left: 60px\"><span style=\"text-align: initial;font-size: 1em\">do {<\/span><\/p>\n<p style=\"padding-left: 90px\"><span style=\"text-align: initial;font-size: 1em\">\u00a0wait (mutex);<\/span><\/p>\n<\/div>\n<div style=\"text-align: justify;padding-left: 30px\">\n<p style=\"padding-left: 150px\">critical section<\/p>\n<p style=\"padding-left: 60px\">signal (mutex);<\/p>\n<p style=\"padding-left: 120px\">remainder section<\/p>\n<\/div>\n<p style=\"text-align: justify;padding-left: 30px\"><span style=\"text-align: initial;font-size: 1em\">} while (1);<\/span><\/p>\n<div style=\"text-align: justify\">\n<p>&nbsp;<\/p>\n<p style=\"text-align: justify\">A semaphore called \u2018mutex\u2019 is used here for guarding a shared resource. The initial value of \u2018mutex\u2019 is set to one. This means that only one process can use the shared resource at a particular time. Process <em>P<\/em>i, before entering its critical section, waits on the semaphore mutex. Process <em>P<\/em>i, after coming out of its critical section, signals the semaphore \u2018mutex\u2019.<\/p>\n<p>&nbsp;<\/p>\n<p style=\"text-align: justify\">Let us now see a sequence of execution of two processes <em>P<\/em><sub>0<\/sub> and <em>P<\/em><sub>1<\/sub>\u00a0 wanting to enter their respective critical sections.<\/p>\n<p>&nbsp;<\/p>\n<p><strong><em>P<\/em><\/strong><strong>0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <\/strong><strong>mutex\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <em>P<\/em><\/strong><strong>1<\/strong><\/p>\n<p>1<\/p>\n<p>wait operation\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0<\/p>\n<\/div>\n<p style=\"text-align: justify\"><span style=\"text-align: initial;font-size: 1em\">Process enters critical section\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0\u00a0wait operation\u00a0<\/span><\/p>\n<div style=\"text-align: justify\">\n<p>\u00a0 \u00a0signal operation \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 1\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0<span style=\"text-align: initial;font-size: 1em\">Process waits<\/span><\/p>\n<p><span style=\"text-align: initial;font-size: 1em\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 0\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0Process enters<\/span><\/p>\n<\/div>\n<div style=\"text-align: justify\">\n<p>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 critical section<\/p>\n<p>1\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0signal operation<\/p>\n<p>&nbsp;<\/p>\n<p style=\"text-align: justify\">Initially, process <em>P<\/em>0 wants to enter its critical section. <em>P<\/em>0 executes the wait operation on the semaphore mutex. Since the value of mutex is 1, the wait operation decrements the value of mutex. The value of mutex becomes 0. <em>P<\/em>0 enters its critical section. In the meantime, if process <em>P<\/em>1 wants to enter its critical section, it executes the wait operation. Since the value of mutex is 0, process <em>P<\/em>1 continues to wait in the while loop <strong>while <em>S<\/em><\/strong>\u00a3 <strong>0 do <em>no-op<\/em>;<\/strong>. When process <em>P<\/em>0 comes out of its critical section, it executes the signal operation on the semaphore mutex. This signal operation increments the value of mutex. The value of mutex now becomes 1. Process <em>P<\/em>1, which is checking the value of mutex in the while loop, now comes out of the while loop, decrements the value of mutex to 0 and enters its critical section.<\/p>\n<p>&nbsp;<\/p>\n<p style=\"text-align: justify\">The implementation of the wait and signal operations on a semaphore that we have seen now has a disadvantage \u2013 busy waiting. That is, when one process is in its critical section, any other process trying to enter its critical section, continuously checks the value of semaphore in the wait operation. Whenever the process waiting to enter its critical section gets the CPU, it executes <strong>while <em>S<\/em><\/strong>\u00a3 <strong>0 do <em>no-op<\/em>;. <\/strong>That is, the process just keeps on checking if <em>S <\/em>\u00a3 0. The value\u00a0<span style=\"font-size: 1em;text-align: initial\">of S is not going to change until this process relinquishes the CPU and some other process changes it. This busy waiting wastes CPU cycles in multi-programmed systems with single CPU. Such a semaphore is called a spinlock.<\/span><\/p>\n<\/div>\n<div style=\"text-align: justify\">\n<p>&nbsp;<\/p>\n<p style=\"text-align: justify\">Let us look at an example to understand spinlock. Let the initial value of semaphore S be 1. Assume that one process acquired a resource after executing a wait on the semaphore S and is continuing to use the resource. Let there be 2 other processes waiting to access the shared resource. Let round robin scheduling be the CPU scheduling algorithm. When the second process gets its CPU time slice, it will execute the while loop continuously in wait till its CPU time slice gets over. During this CPU time slice, the CPU time is used without doing any useful work. After this time slice, the third process gets its time slice. The third process also uses its entire time slice by just checking in the while loop of wait. The CPU\u2019s time is not used for any useful work. Thus it is seen that spinlock wastes CPU time.<\/p>\n<p>&nbsp;<\/p>\n<p style=\"text-align: justify\">Spinlock is useful in multiprocessor systems. The advantage of spinlock is that no context switch is required when a process must wait on a lock. This is useful when locks are for short times.<\/p>\n<p>&nbsp;<\/p>\n<p style=\"text-align: justify\">To overcome this busy waiting, the definitions of the wait and signal operations of the semaphore are modified. The semaphore is implemented as a structure or a record, rather than as just a variable. The structure has two members, an integer value and a list of processes associated with the semaphore.<\/p>\n<p>&nbsp;<\/p>\n<p>The semaphore is defined as follows:<\/p>\n<p>typedef struct {<\/p>\n<p style=\"padding-left: 30px\">int value;<\/p>\n<p style=\"padding-left: 30px\">struct process *L;<\/p>\n<p>} semaphore;<\/p>\n<p>&nbsp;<\/p>\n<p style=\"text-align: justify\">Two operations are defined on processes associated with the semaphore, the block and the wakeup operations. The block operation suspends the process that invokes it. The wakeup(P) operation resumes the execution of a blocked process P.<\/p>\n<p>&nbsp;<\/p>\n<p>The wait and signal operations on a semaphore are now defined as<\/p>\n<p>&nbsp;<\/p>\n<p><strong><em>wait<\/em><\/strong><strong>(S):<\/strong><\/p>\n<p style=\"padding-left: 30px\">S.value&#8211;;<\/p>\n<p style=\"padding-left: 30px\">if (S.value &lt; 0)<\/p>\n<p style=\"padding-left: 30px\">{<\/p>\n<p style=\"padding-left: 90px\">add this process to S.L;<\/p>\n<p style=\"padding-left: 90px\">block;<\/p>\n<p style=\"padding-left: 30px\">}<\/p>\n<p>&nbsp;<\/p>\n<p style=\"text-align: justify\">Here S is the semaphore structure. It has an integer value (S.value) and a list of processes (S.L) associated with it. In the wait operation, the value of the semaphore is first decremented (S.value&#8211;;). Then the value of the semaphore is checked. If the value of the semaphore is less than zero, it means that the resource is not available. Therefore, the process that is executing wait is added to the list associated with the semaphore and is blocked (i.e., put to the waiting state). Compared to the earlier implementation of the wait operation, here the process does not keep on checking the value of the semaphore. Once the resource becomes available, this process is moved out of the waiting state and the process accesses the shared\u00a0<span style=\"font-size: 1em;text-align: initial\">resource.<\/span><\/p>\n<\/div>\n<div style=\"text-align: justify\">\n<p>&nbsp;<\/p>\n<p><strong><em>signal(S<\/em><\/strong><strong>):<\/strong><\/p>\n<p style=\"padding-left: 30px\">S.value++;<\/p>\n<p style=\"padding-left: 30px\">if (S.value &lt;= 0)<\/p>\n<p style=\"padding-left: 30px\">{<\/p>\n<p style=\"padding-left: 60px\">remove a process P from S.L;<\/p>\n<p style=\"padding-left: 60px\">wakeup(P);<\/p>\n<p style=\"padding-left: 30px\">}<\/p>\n<p>&nbsp;<\/p>\n<p style=\"text-align: justify\">In the signal operation, the value of the semaphore is incremented. This means that one more process can access the resource. Then the value of the semaphore is checked. If the value of the semaphore is less than or equal to zero, one of the waiting processes is woken up. The process that is woken up is moved to the ready state and can access the resource.<\/p>\n<p>&nbsp;<\/p>\n<p style=\"text-align: justify\">The value of the semaphore is less than or equal to zero only if there are other processes waiting in the list associated with this semaphore. (The value had become less than zero when other processes had decremented the value of the semaphore earlier while executing wait).<\/p>\n<p>&nbsp;<\/p>\n<p><strong>14.3\u00a0 Semaphore as a General Synchronization Tool\u00a0<\/strong><\/p>\n<p>&nbsp;<\/p>\n<p style=\"text-align: justify\">In this section, we see how the semaphore can be used as a synchronization tool. There are two processes <em>P<\/em>i and <em>P<\/em>j that want to access a common resource. Let <em>flag <\/em>be the semaphore that guards the shared resource. The shared resource can be used by only one process at a time. Therefore, the value of the semaphore <em>flag <\/em>is initialized to 1.<\/p>\n<p>&nbsp;<\/p>\n<p><strong><em>P<\/em><\/strong><strong>i\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <\/strong><strong>Semaphore\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <em>P<\/em><\/strong><strong>j<\/strong><\/p>\n<p><span style=\"text-align: initial;font-size: 1em\">flag = 1<\/span><\/p>\n<p><span style=\"text-align: initial;font-size: 1em\">wait(flag)\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0<\/span><\/p>\n<p><span style=\"text-align: initial;font-size: 1em\">access resource\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0\u00a0\u00a0flag = 0<\/span><\/p>\n<p>&nbsp;<\/p>\n<p><span style=\"text-align: initial;font-size: 1em\">signal(flag)\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0\u00a0<\/span><\/p>\n<\/div>\n<div style=\"text-align: justify\">\n<p>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0<span style=\"text-align: initial;font-size: 1em\">flag = -1\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0wait(flag)<\/span><\/p>\n<p>flag = 0<\/p>\n<p>access resource\u00a0signal(flag)<\/p>\n<p>flag = 1<\/p>\n<\/div>\n<div style=\"text-align: justify\">\n<p>&nbsp;<\/p>\n<p style=\"text-align: justify\">Process <em>P<\/em>i executes the wait operation on the semaphore. The wait operation decrements the value of the semaphore <em>flag<\/em>. <em>flag <\/em>becomes zero. Since the value of <em>flag <\/em>is not less than zero, <em>P<\/em>i can access the resource. In the meantime, if <em>P<\/em>j wants to access the resource, <em>P<\/em>j executes the wait operation on the semaphore <em>flag<\/em>. <em>flag <\/em>is decremented and becomes -1. Since the value of <em>flag <\/em>is &lt; 0, <em>P<\/em>j is added to the list associated with the semaphore and is put to the waiting state.<\/p>\n<p>&nbsp;<\/p>\n<p style=\"text-align: justify\">When process <em>P<\/em>i completes the usage of the resource, it executes the signal operation on <em>flag<\/em>. The value of <em>flag <\/em>is incremented and becomes 0. Process <em>P<\/em>j is woken up from the sleeping state. Process <em>P<\/em>j now can access the resource. After <em>P<\/em>j completes using the resource,\u00a0<em style=\"font-size: 1em;text-align: initial\">P<\/em><span style=\"font-size: 1em;text-align: initial\">j executes the signal operation and the value of <\/span><em style=\"font-size: 1em;text-align: initial\">flag <\/em><span style=\"font-size: 1em;text-align: initial\">is incremented back to 1.<\/span><\/p>\n<\/div>\n<div style=\"text-align: justify\">\n<p>&nbsp;<\/p>\n<p>In this way, a semaphore can be used for safeguarding resources.<\/p>\n<p>&nbsp;<\/p>\n<p><strong>14.4\u00a0 Deadlock and Starvation\u00a0<\/strong><\/p>\n<p>&nbsp;<\/p>\n<p style=\"text-align: justify\">When semaphores are used for synchronization, it is possible to have deadlocks and starvation. Deadlock is a situation where two or more processes are waiting indefinitely for an event that can be caused by only one of the waiting processes. For example, when two or more processes are waiting for the release of some resource that is held by another waiting process, it is a deadlock. Every process in a set of processes will be waiting for an event caused by one of the processes in the set. Starvation means indefinite blocking. A process may never be removed from the semaphore queue in which it is suspended and it starves.<\/p>\n<p>&nbsp;<\/p>\n<p style=\"text-align: justify\">Let us now see how deadlocks and starvation can happen with semaphores. Let <em>S <\/em>and <em>Q <\/em>be two semaphores initialized to 1. That is, semaphore <em>S <\/em>is safeguarding a resource that can be accessed by only one process at a time. Similarly, semaphore <em>Q <\/em>is also safeguarding another resource that can be accessed by only one process at a time.<\/p>\n<p style=\"padding-left: 180px\"><em>P<\/em><sub>0<\/sub>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <em>P<\/em><sub>1<\/sub><\/p>\n<p style=\"padding-left: 180px\"><em>wait<\/em>(<em>S<\/em>);\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <em>wait<\/em>(<em>Q<\/em>);<\/p>\n<p style=\"padding-left: 180px\"><em>wait<\/em>(<em>Q<\/em>);\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <em>wait<\/em>(<em>S<\/em>);<\/p>\n<p style=\"padding-left: 180px\">\u00a0 \u00a0 :\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 :<\/p>\n<p style=\"padding-left: 180px\"><em>signal<\/em>(<em>S<\/em>);\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <em>signal<\/em>(<em>Q<\/em>);<\/p>\n<p style=\"padding-left: 180px\"><em>signal<\/em>(<em>Q<\/em>)\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <em>signal<\/em>(<em>S<\/em>);<\/p>\n<p>&nbsp;<\/p>\n<p style=\"text-align: justify\">Consider two processes <em>P<\/em>0 and <em>P<\/em>1. <em>P<\/em>0 executes wait(S) and at the same time, <em>P<\/em>1 executes wait(Q). The values of the semaphores S and Q become 0. <em>P<\/em>0 then executes wait(Q) and waits till semaphore Q is signaled. <em>P<\/em>1 then executes wait(S) and waits till the semaphore S is signaled. Here, we see that process <em>P<\/em>0 is waiting for a resource held by <em>P<\/em>1 and process <em>P<\/em>1 is held by a resource held by <em>P<\/em>0. Each of the two processes is waiting for a resource held by the other process. Therefore, both are unable to proceed. Both the processes wait indefinitely. Both the processes are caught in a deadlock and are starving.<\/p>\n<p>&nbsp;<\/p>\n<p style=\"text-align: justify\">Therefore, the order in which wait and signal are used in processes should be selected carefully. Else, it may result in deadlocks and starvation also.<\/p>\n<p>&nbsp;<\/p>\n<p style=\"text-align: justify\">Starvation is indefinite blocking. Starvation can also happen when processes that are added to the semaphore queue are removed in a last in first out manner. That is, whenever processes wait for a resource guarded by a semaphore, the processes are added to the queue associated with the semaphore. When more processes wait for the same resource, all these processes are also added to the end of the semaphore\u2019s queue. While removing processes from the queue, if the processes are removed from the end, the processes that were added first will starve.<\/p>\n<p>&nbsp;<\/p>\n<p><strong>14.5\u00a0 \u00a0Types of Semaphores\u00a0<\/strong><\/p>\n<p>&nbsp;<\/p>\n<p style=\"text-align: justify\">There are two types of semaphores\u2014counting semaphores and binary semaphores. A counting semaphore takes an integer value that can range over an unrestricted domain. The semaphores that we discussed in the previous sections are counting semaphores. They are called counting semaphores because the value of the semaphores can be any integer value. A binary semaphore takes an integer value that can range only between 0 and 1. Hence, a binary\u00a0<span style=\"text-align: initial;font-size: 1em\">semaphore can be simpler to implement than counting semaphores. If we have the implementation of binary semaphores, we can implement\u00a0 counting semaphores using the implementation of binary semaphores.<\/span><\/p>\n<\/div>\n<div style=\"text-align: justify\">\n<p>&nbsp;<\/p>\n<p style=\"text-align: justify\">We now see how a counting semaphore <em>S <\/em>can be implemented using binary semaphores. S1 and S2 are the binary semaphores using which the counting semaphore S is implemented. C is an ordinary variable and the initial value of C is set to the initial value of the counting\u00a0semaphore S. The initial value of the counting semaphore S indicates the number of processes that can access the resource guarded by the semaphore S at the same time.<\/p>\n<p>&nbsp;<\/p>\n<p><strong>Data structures:<\/strong><\/p>\n<p style=\"padding-left: 60px\">binary-semaphore S1, S2;<\/p>\n<p style=\"padding-left: 60px\">int C;<\/p>\n<p>&nbsp;<\/p>\n<p style=\"padding-left: 30px\">S1 and S2 are two binary semaphores and C is an integer variable.<\/p>\n<p>&nbsp;<\/p>\n<p><strong><span style=\"text-align: justify;font-size: 1em\">Initialization:<\/span><\/strong><\/p>\n<\/div>\n<div style=\"text-align: justify;padding-left: 90px\"><span style=\"text-align: initial;font-size: 1em\">S1 = 1<\/span><\/div>\n<div style=\"text-align: justify;padding-left: 90px\"><span style=\"text-align: initial;font-size: 1em\">S2 = 0<\/span><\/div>\n<div style=\"text-align: justify;padding-left: 90px\"><span style=\"text-align: initial;font-size: 1em\">C = initial value of semaphore S<\/span><\/div>\n<p style=\"text-align: justify;padding-left: 60px\"><span style=\"text-align: initial;font-size: 1em\">C is assigned the initial value of the counting semaphore S. The initial values of S1 and S2 are assigned 1 and 0 respectively.<\/span><\/p>\n<div style=\"text-align: justify\">\n<p>&nbsp;<\/p>\n<p><strong>Wait and signal operations for binary semaphore:\u00a0<\/strong><\/p>\n<\/div>\n<div style=\"text-align: justify\">\n<p>&nbsp;<\/p>\n<p>If S1 is a binary semaphore, then the wait operation on the binary semaphore is given\u00a0below:<\/p>\n<p>&nbsp;<\/p>\n<p>wait(S1)<\/p>\n<p>{<\/p>\n<\/div>\n<p style=\"text-align: justify;padding-left: 60px\"><span style=\"text-align: initial;font-size: 1em\">while(S1==0)<\/span><\/p>\n<p style=\"text-align: justify;padding-left: 60px\"><span style=\"text-align: initial;font-size: 1em\">; S1&#8211;;<\/span><\/p>\n<div style=\"text-align: justify\">\n<p style=\"padding-left: 30px\">}<\/p>\n<p>&nbsp;<\/p>\n<p>If the value of the binary semaphore is zero, the process that executes the wait operation, waits in the while loop. If the value is not equal to zero, the process comes out of the while loop and decrements the value of the semaphore.<\/p>\n<p>&nbsp;<\/p>\n<p>signal(S1)<\/p>\n<p>{<\/p>\n<p style=\"padding-left: 30px\">S1++;<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>In the signal operation, the value of the binary semaphore is incremented.<\/p>\n<p>&nbsp;<\/p>\n<p>The wait and signal operations of the counting semaphore are given below:<\/p>\n<p>&nbsp;<\/p>\n<p><strong><em>wait <\/em><\/strong><strong>operation<\/strong><\/p>\n<p>The wait operation on the counting semaphore can be implemented using wait and signal operations on the binary semaphore as given below:<\/p>\n<p>&nbsp;<\/p>\n<p>wait(S1);<\/p>\n<p>C&#8211;;<\/p>\n<p>if (C &lt; 0) {<\/p>\n<p style=\"padding-left: 30px\"><span style=\"text-align: initial;font-size: 1em\">signal(S1);<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"text-align: initial;font-size: 1em\">wait(S2);<\/span><\/p>\n<p><span style=\"text-align: initial;font-size: 1em\">}<\/span><\/p>\n<p><span style=\"text-align: initial;font-size: 1em\">signal(S1);\u00a0<\/span><\/p>\n<\/div>\n<div style=\"text-align: justify\">\n<p>&nbsp;<\/p>\n<p style=\"text-align: justify\">The initial value of S1 is 1. Therefore, the wait operation on S1, finds that the value of S1 is not zero and decrements the value of S1. Next, the value of C is decremented. The initial value of C is equal to the value of the counting semaphore S. If the value of C becomes less than zero, then the process executing wait cannot proceed to execute its critical section. It has to wait. Therefore, the process signals S1 semaphore; the value of S1 becomes 1. Then, it waits on semaphore S2. Since the initial value of S2 is 0, the process waits on S2. If the value of C is not less than 0, it means that the process can enter its critical section. In this case, the process signals S1 and proceeds to enter its critical section. Here, we can see that the semaphore S1 guards the decrement of the variable C. The process waits on S1 before decrementing C and signals S1 after decrementing C. Semaphore S2 guards the shared resource.<\/p>\n<p>&nbsp;<\/p>\n<p><strong><em>signal <\/em><\/strong><strong>operation<\/strong><\/p>\n<p>&nbsp;<\/p>\n<p style=\"text-align: justify\">The signal operation on S is also implemented using wait and signal operations on S1 and S2. The implementation of signal(S) is given below:<\/p>\n<p>&nbsp;<\/p>\n<p>wait(S1);<\/p>\n<p>C ++;<\/p>\n<p>if (C &lt;= 0)<\/p>\n<p style=\"padding-left: 30px\">signal(S2);<\/p>\n<p><span style=\"text-align: initial;font-size: 1em\">else<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"text-align: initial;font-size: 1em\">signal(S1);<\/span><\/p>\n<\/div>\n<div style=\"text-align: justify\">\n<p>&nbsp;<\/p>\n<p style=\"text-align: justify\">The executing process first waits on S1. If no other process is currently incrementing or decrementing C, the value of S1 will be 1. wait(S1) decrements the value of S1 to 0. Then, C is incremented. If the value of C becomes less than or equal to zero, then it means that there is(are) other process(es) waiting to use the shared resource. In that case, signal(S2) is executed. As mentioned earlier, S2 is the semaphore that guards the shared resource. When signal(S2) is executed, another process waiting on S2 will come out of waiting, signal S1 (this is the signal(S1) in the wait operation) and proceed\u00a0 to use the shared\u00a0 resource. If C &gt; 0, signal(S1) (in the signal operation) is executed.<\/p>\n<p>&nbsp;<\/p>\n<p>Let us see with an example, how a counting semaphore is implemented using binary semaphores. Let C = 2 (initial value of semaphore S). Since the value of semaphore S is 2, two processes can use the shared resource at the same time. Let us see what happens when three processes want to use the shared resource at the same time.<\/p>\n<p>&nbsp;<\/p>\n<p>When wait(S) is executed by the first process, say <em>P<\/em><sub>0<\/sub><\/p>\n<p>&nbsp;<\/p>\n<p><strong>wait(S) by <em>P<\/em><sub>0<\/sub>:\u00a0<\/strong><\/p>\n<p>&nbsp;<\/p>\n<p><strong>S<\/strong><strong>1\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0C\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 S2<\/strong><\/p>\n<p>1\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 2\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0<\/p>\n<p>0<\/p>\n<p>1<\/p>\n<p>1<\/p>\n<\/div>\n<p>&nbsp;<\/p>\n<p style=\"text-align: justify\"><span style=\"text-align: initial;font-size: 1em\">Initially, S1 is 0, C is 2 and S2 is 0. wait(S1) decrements the value of S1 to 0. Then C is decremented from 2 to 1. signal(S1) increments the value of S1 back to 1. <\/span><em style=\"text-align: initial;font-size: 1em\">P<\/em><span style=\"text-align: initial;font-size: 1em\">0 gets access to the shared resource.<\/span><\/p>\n<div style=\"text-align: justify\">\n<p>&nbsp;<\/p>\n<p>In the meantime, suppose process <em>P<\/em>1 \u00a0wants to access the shared resource. The sequence is shown below:<\/p>\n<p>&nbsp;<\/p>\n<p><strong>wait(S) by <em>P<\/em><sub>1<\/sub>:\u00a0<\/strong><\/p>\n<p>&nbsp;<\/p>\n<p><strong>S<\/strong><strong>1\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0C\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 S2<\/strong><\/p>\n<p>1\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 1\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0<\/p>\n<p>0<\/p>\n<p>0<\/p>\n<p>1<\/p>\n<p>&nbsp;<\/p>\n<p style=\"text-align: justify\">wait(S1) decrements the value of S1 from 1 to 0.Then C is decremented from 1 to 0. signal(S1) increments the value of S1 back to 1. <em>P<\/em>1 gets access to the shared resource.<\/p>\n<p>&nbsp;<\/p>\n<p style=\"text-align: justify\">In the meantime, suppose the third process <em>P<\/em>2 \u00a0wants to access the shared resource. The sequence is shown below:<\/p>\n<p>&nbsp;<\/p>\n<p><strong>wait(S) by <em>P<\/em><sub>2<\/sub>:\u00a0<\/strong><\/p>\n<p>&nbsp;<\/p>\n<p><strong>S<\/strong><strong>1\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0C\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 S2<\/strong><\/p>\n<p>1\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0<\/p>\n<p>0<\/p>\n<p>-1<\/p>\n<p>1\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Process <em>P<\/em>2 waits on S2<\/p>\n<p>&nbsp;<\/p>\n<p style=\"text-align: justify\">wait(S1) decrements the value of S1 from 1 to 0.Then C is decremented from 0 to -1. Since the value of C goes below 0, process <em>P<\/em>2 executes wait(S2). <em>P<\/em>2 does not get access to the shared resource. Since the initial value of the semaphore S was 2, only two processes are able to access the shared resource. The other processes wait.<\/p>\n<p>&nbsp;<\/p>\n<p>Let <em>P<\/em>0 complete the usage of the shared resource. <em>P<\/em>0 executes signal(S). The changes in the semaphores\u2019 values are shown below:<\/p>\n<p>&nbsp;<\/p>\n<p><strong>When signal(S) is executed by <em>P<\/em><sub>0<\/sub>:\u00a0<\/strong><\/p>\n<p>&nbsp;<\/p>\n<p><strong>S<\/strong><strong>1\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 C\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 S2<\/strong><\/p>\n<p>1\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 -1\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0<\/p>\n<p>0<\/p>\n<p><span style=\"text-align: initial;font-size: 1em\">0<\/span><\/p>\n<p><span style=\"text-align: initial;font-size: 1em\">Released process <\/span><em style=\"text-align: initial;font-size: 1em\">P<\/em><sub style=\"text-align: justify\"><span style=\"text-align: initial\">2\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <\/span><\/sub><span style=\"text-align: initial\">1<\/span><\/p>\n<p><span style=\"text-align: initial;font-size: 1em\">signals S1 1\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0<\/span><span style=\"text-align: initial;font-size: 1em\">Process <\/span><em style=\"text-align: initial;font-size: 1em\">P<\/em><span style=\"text-align: initial;font-size: 1em\">2 \u00a0waiting on S2 is released<\/span><\/p>\n<\/div>\n<p>&nbsp;<\/p>\n<p style=\"text-align: justify\">wait(S1) in the signal operation decrements the value of S1 from 1 to 0.Then C is incremented from \u20131 to 0. Since the value of C becomes 0, signal(S2) is executed. Process <em>P<\/em>2 waiting on S2 is released. Process <em>P<\/em>2 signals S1 (signal(S1) in the wait operation) and gains access to the shared resource.<\/p>\n<p>&nbsp;<\/p>\n<p style=\"text-align: justify\"><strong>When signal(S) is executed by <em>P<\/em><sub>1<\/sub>:<\/strong><\/p>\n<p>&nbsp;<\/p>\n<p style=\"text-align: justify\"><strong>S<\/strong><strong>1\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0C\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 S2<\/strong><\/p>\n<p style=\"text-align: justify\">1\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0<\/p>\n<p style=\"text-align: justify\">0<\/p>\n<p style=\"text-align: justify\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 1<\/p>\n<p style=\"text-align: justify\">1<\/p>\n<p style=\"text-align: justify\">wait(S1) in the signal operation\u00a0 decrements the value of S1 from 1 to 0.\u00a0 Then C is incremented from 0 to 1. Since the value of C becomes greater than 0, signal(S1) is executed. The value of S1 is changed from 0 to 1. Thus, we see that a counting semaphore can be implemented using binary semaphores.<\/p>\n<p>&nbsp;<\/p>\n<p style=\"text-align: justify\"><strong>14.6\u00a0 \u00a0Summary<\/strong><\/p>\n<p>&nbsp;<\/p>\n<p style=\"text-align: justify\">In this module, we learnt how a semaphore can be used as a synchronization tool. We understood that there are two types of semaphores \u2013 counting and binary semaphores. We also learnt how a counting semaphore is implemented using binary semaphores.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p style=\"text-align: justify\"><strong>References<\/strong><\/p>\n<ol>\n<li style=\"text-align: justify\">Abraham Silberschatz, Peter B. Galvin, Greg Gagne, \u201cOperating System Concepts\u201d, Ninth Edition, John Wiley &amp; Sons Inc., 2012.<\/li>\n<\/ol>\n","protected":false},"author":4,"menu_order":11,"template":"","meta":{"pb_show_title":"on","pb_short_title":"","pb_subtitle":"","pb_authors":["dr-mary-anitha-rajam"],"pb_section_license":""},"chapter-type":[],"contributor":[58],"license":[],"class_list":["post-141","chapter","type-chapter","status-publish","hentry","contributor-dr-mary-anitha-rajam"],"part":3,"_links":{"self":[{"href":"https:\/\/ebooks.inflibnet.ac.in\/csp3\/wp-json\/pressbooks\/v2\/chapters\/141","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ebooks.inflibnet.ac.in\/csp3\/wp-json\/pressbooks\/v2\/chapters"}],"about":[{"href":"https:\/\/ebooks.inflibnet.ac.in\/csp3\/wp-json\/wp\/v2\/types\/chapter"}],"author":[{"embeddable":true,"href":"https:\/\/ebooks.inflibnet.ac.in\/csp3\/wp-json\/wp\/v2\/users\/4"}],"version-history":[{"count":5,"href":"https:\/\/ebooks.inflibnet.ac.in\/csp3\/wp-json\/pressbooks\/v2\/chapters\/141\/revisions"}],"predecessor-version":[{"id":416,"href":"https:\/\/ebooks.inflibnet.ac.in\/csp3\/wp-json\/pressbooks\/v2\/chapters\/141\/revisions\/416"}],"part":[{"href":"https:\/\/ebooks.inflibnet.ac.in\/csp3\/wp-json\/pressbooks\/v2\/parts\/3"}],"metadata":[{"href":"https:\/\/ebooks.inflibnet.ac.in\/csp3\/wp-json\/pressbooks\/v2\/chapters\/141\/metadata\/"}],"wp:attachment":[{"href":"https:\/\/ebooks.inflibnet.ac.in\/csp3\/wp-json\/wp\/v2\/media?parent=141"}],"wp:term":[{"taxonomy":"chapter-type","embeddable":true,"href":"https:\/\/ebooks.inflibnet.ac.in\/csp3\/wp-json\/pressbooks\/v2\/chapter-type?post=141"},{"taxonomy":"contributor","embeddable":true,"href":"https:\/\/ebooks.inflibnet.ac.in\/csp3\/wp-json\/wp\/v2\/contributor?post=141"},{"taxonomy":"license","embeddable":true,"href":"https:\/\/ebooks.inflibnet.ac.in\/csp3\/wp-json\/wp\/v2\/license?post=141"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}