PV operations and semaphores implement process synchronization (mutex access to multiple critical resources)

Source: Internet
Author: User

Process Synchronization is one of the most discussed topics in multithreading. In most development languages, they all have their own methods or implementations to implement process synchronization. But in the final analysis, the methods they implement are based on the Process Synchronization of the operating system. Today, let's take a look at how processes are synchronized at the underlying operating system level. In computer operating systems, PV operations are an important method in process management, which is both important and difficult. Before looking at the PV operation, let's look at another important concept --Semaphores.


What is semaphores?The data structure of semaphore is a value and a pointer. The Pointer Points to the next process waiting for the semaphore. The semaphore value is related to the usage of the corresponding resource. When its value is greater than 0, it indicates the number of currently available resources; when its value is less than 0, its absolute value indicates the number of processes waiting to use this resource. Note that the semaphore value can only be changed by the PV operation. Semaphore (semaphore) is a facility used in a multi-threaded environment. It can be used to ensure that two or more key code segments are not concurrently called. Before entering a key code segment, the thread must obtain a semaphore. Once the key code segment is complete, the thread must release the semaphore. Other threads that want to enter the key code segment must wait until the first thread releases the semaphore. To complete this process, you need to create a semaphore VI, and then place acquire semaphore VI and release semaphore VI at the first end of each key code segment respectively. Make sure that these semaphores VI reference the initial semaphores.


Generally, when semaphores S> = 0, s indicates the number of available resources. Executing a P operation means that one unit resource is allocated to the request. Therefore, the value of S is reduced by 1. When S <0, no resources are available. The requester must wait for other processes to release such resources, it can run. Executing a V operation means releasing a unit resource. Therefore, the value of S is increased by 1. If S <= 0, some processes are waiting for this resource, therefore, you need to wake up a waiting process to run it.


The general model for mutual exclusion of processes using semaphores and PV operations is:


Process P1 process P2 ...... Process PN
...... ...... ......
P (S );
Critical section; critical section;
V (s );
...... ...... ...... ......


Semaphores are used for mutual exclusion. The initial value is 1.


Note the following when using the PV operation to achieve process mutex:
(1) The P and V operations that are mutually exclusive to the user in each program must appear in pairs. First, P operations are performed to enter the critical section, and then v operations are performed to output the critical section. If multiple branches exist, check their pairs carefully.
(2) P and V operations should be respectively close to the head and tail of the critical section. The code of the critical section should be as short as possible and there should be no endless loops.
(3) The initial value of mutex semaphores is generally 1.


PV operations are one of the typical synchronization mechanisms. A semaphore is used to associate a message. When the semaphore value is 0, it indicates that the expected message has not been generated. If the semaphore value is not 0, it indicates that the expected message already exists. When processes are synchronized using the PV operation, call the P operation to test whether the message arrives, and call the V operation to send the message.


Two primitive operations can be performed on a semaphore variable: P operation and V operation, which are defined as follows:

Method p(var s:samephore);  {  s.value=s.value-1;  if (s.value>0) asleep(s.next);  }  Method  v(var s:samephore);  {  s.value=s.value+1;  if (s.value<=0) wakeup(s.next);  }  

 

Two standard processes are used:

Asleep (S. Next); the PCB of the process that executes this operation enters the end of S. Next, and the process changes to the waiting state.

Wakeup (S. Queue); wake up the process in the S. Queue header and insert it into the ready queue.

When the initial value of S. value is 1, it can be used to achieve mutual exclusion of processes.

 

P and V Operations are non-disruptive program segments, called primitives. If semaphores are treated as shared variables, PV operations are the critical section. Multiple processes cannot be executed at the same time, which is generally ensured by hardware. A semaphore can only be set to an initial value once. In the future, only P or V operations can be performed on it. It can also be seen that the semaphore mechanism must have public memory and cannot be used in distributed operating systems. This is its biggest weakness.

The main operations of the V primitive are:

(1) Value plus 1;

(2) If the sum result is greater than zero, the process continues to execute;

(3) If the sum result is less than or equal to zero, a process blocked on the semaphore will be awakened, and then the original process will be returned for further execution or process scheduling.

In the concurrent development of Java JDK, I am provided with a similar semaphore class-semaphore. The acquire () and release () methods are equivalent to P and V Operations, the special feature of these two methods is that operations on semaphore objects are atomic operations supported by the underlying operating system. Next, let's take a look at how to use Java to implement the dining of classical philosophers.

Import Java. util. concurrent. semaphore; Class signs {final static int thinking = 0; // philosopher's state thingingfinal static int eating = 1; // The state of the philosopher eatingstatic int [] status = new int [5]; // The state of the philosopher, which defaults to thingingstatic semaphore [] S = NULL; // semaphore: record whether philosophers can eat meals. If not, block static semaphore mutex = new semaphore (1); // mutex access semaphores (Binary semaphores) in the critical section ), equivalent to mutex lock // initialize the meal semaphores of every philosopher. The default value cannot be static {S = new semaphore [5]; for (INT I = 0; I <S. length; I ++) s [I] = new semap Hore (0) ;};} class philosopher implements runnable {private int PID; // The current philosopher's serial number private int lid; // The Philosopher's serial number private int rid sitting on the left hand side; // The philosopher serial number philosopher (int id) {This. PID = ID; this. lid = (ID + 4) % 5; this. rid = (ID + 1) % 5;} private void test (int pid) {// If none of the current philosophers eat at the left and right sides, then the current philosopher can eat if (signs. status [pid] = signs. thinking & signs. status [lid]! = Signs. Eating & signs. status [RID]! = Signs. eating) {signs. status [pid] = signs. eating; // at this time, the philosopher's thread can eat, but other philosophers may not eat signs. s [pid]. release (); // release a license} public void run () {try {// try to pick up the fork to prepare for the meal signs. mutex. acquire (); test (PID); signs. mutex. release (); // judge the dining semaphore of the current philosopher. If the meal cannot be permitted, the current thread blocks signs. s [pid]. acquire (); system. out. println ("#" + PID + "philosophers are eating... "); // put down the forks and wake up the two philosophers next to them to try to eat signs. mutex. acquire (); signs. status [pid] = signs. thinking; test (LID); // Let the philosopher on the left side try to pick up the fork. If yes, release the philosopher's semaphore license test (RID); // same as signs. mutex. release ();} catch (interruptedexception e) {e. printstacktrace () ;}} public class test {public static void main (string [] ARGs) {New thread (New philosopher (0 )). start (); New thread (New philosopher (1 )). start (); New thread (New philosopher (2 )). start (); New thread (New philosopher (3 )). start (); New thread (New philosopher (4 )). start ();}}

For more java code implementation thread synchronization problems, see: http://hxraid.iteye.com/blog/739265


Bytes ------------------------------------------------------------------------------------------------------------

The electronic book "Java programmers from stupid birds to cainiao" is officially released. You are welcome to download it.

Http://blog.csdn.net/csh624366188/article/details/7999247




Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.