AND型信号量与信号量集-----进程的同步与互斥面向对象的解决方案(二)

AND型信号量

上述的进程互斥问题,是针对各进程之间只共享一个临界资源而言的。在有些应用场合,是一个进程需要先获得两个或更多的共享资源后方能执行其任务。假定现有两个进程AB,他们都要求访问共享数据DE。当然,共享数据都应作为临界资源。为此,可为这两个数据分别设置用于互斥的信号量DmutexEmutex,并令它们的初值都是1;

AND同步机制的基本思想是:将进程在整个运行过程中需要的所有资源,一次性全部地分配给进程,待进程使用完后再一起释放。只要尚有一个资源未能分配给进程,其它所有可能为之分配的资源也不分配给它。亦即,对若干个临界资源的分配,采取原子操作方式:要么把它所请求的资源全部分配到进程,要么一个也不分配。由死锁理论可知,这样就可避免上述死锁情况的发生。为此,在wait操作中,增加了一个“AND”条件,故称为AND同步,或称为同时wait操作,

伪代码:如下:

Swait(S1S2,…,Sn)

  if Si>=1 and … and Sn>=1 then

   for i:=1 to n do

   Si:=Si-1

   endfor

  else

  place the process in the waiting queue associated with the first Si found with Si<1and set the program count of this process to the beginning of Swait operation 

  endif

Ssignal(S1S2,…,Sn)

for i:=1 to n do

  Si:=Si+1

Remove all the process waiting in the queue associated with Si into the ready queue.

endfor; 

Java代码:

package org.hao.andpv;

 

import java.util.ArrayList;

import java.util.List;

import java.util.concurrent.BlockingQueue;

import java.util.concurrent.LinkedBlockingQueue;

 

public class AndPV {

private int[] semaphores;//信号量数组

private List> queueList=new ArrayList>();

    //每个信号量对应的阻塞队列

public AndPV(int[] semaphores) {//设置信号量初值,初始化

this.semaphores=semaphores;

for(int i=0;i

queueList.add(new LinkedBlockingQueue());

}

}

public synchronized void p(Thread t) {//p原语

int semaphoreIndex=0;

for(;semaphoreIndex判断每个条件是否都满足

if(semaphores[semaphoreIndex]<1){//semaphoreIndex个条件不满足

break;

}

}

if(semaphoreIndex条件不满足时

queueList.get(semaphoreIndex).add(t);//添加到阻塞队列

try {

synchronized(t){       

   t.wait();//线程阻塞

}

} catch (Exception e) {

}

}else{

for(semaphoreIndex=0;semaphoreIndex

     semaphores[semaphoreIndex]--;//条件满足时,可用资源都减一

}

}

}

public synchronized void v(){ //v原语

for(int semaphoreIndex=0;semaphoreIndex

semaphores[semaphoreIndex]++;//进程运行完,可用资源都增一

if(semaphores[semaphoreIndex]>=0){//semaphoreIndex类有可用资源

Thread t=queueList.get(semaphoreIndex).poll();

synchronized(t){

   t.notify();

   p(t);//判断其他条件是否满足

}

}

}

}

 

}

信号量集

  在记录型信号量机制中,wait(S)signal(S)操作仅能对信号量施以加1或减1操作,意味着每次只能获得或释放一个单位的临界资源。而当一次需要N个某类临界资源时,便要进行Nwait(S)操作,显然这是低效的。此外,在有些情况下,当资源数量低于某一下限值时,便不予以分配。因而,在每次分配之前,都必须测试该资源的数量,看其是否大于其下限值。基于上述两点,可以对AND信号量机制加以扩充,形成一般化的“信号量集”机制。Swait操作可描述如下,其中S为信号量,d为需求值,而t为下限值。 

package org.hao.andpv;

 

import java.util.ArrayList;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

import java.util.concurrent.BlockingQueue;

import java.util.concurrent.LinkedBlockingQueue;

 

public class CollectPV {

private int[] semaphores;

private List> queueList=new ArrayList>();

    private Map map=new HashMap();//保存第线程的请求

public CollectPV(int[] semaphores) {

this.semaphores=semaphores;

for(int i=0;i

queueList.add(new LinkedBlockingQueue());

}

}

public synchronized void p(Thread t,Integer[] semas) {

try {

int semaphoreIndex=0;

for(;semaphoreIndex

if(semaphores[semaphoreIndex]

break;

}

}

if(semaphoreIndex

BlockingQueue blockingQueue=queueList.get(semaphoreIndex);

blockingQueue.add(t);

queueList.add(semaphoreIndex, blockingQueue);

map.put(t, semas);

try {

synchronized(t){       

   t.wait();

}

} catch (Exception e) {

}

}else{

for(int semaphoresIndex=0;semaphoresIndex

     semaphores[semaphoresIndex]-=semas[semaphoresIndex];

}

}

} catch (Exception e) {

}

}

public synchronized void v(Integer[] semas){

try {

for(int semaphoreIndex=0;semaphoreIndex

semaphores[semaphoreIndex]+=semas[semaphoreIndex];

if(semaphores[semaphoreIndex]>=0){

Thread t=queueList.get(semaphoreIndex).poll();

synchronized(t){

   t.notify();

   p(t, map.get(t));

}

}

}

} catch (Exception e) {

}

}

 

}

 

你可能感兴趣的:(AND型信号量与信号量集-----进程的同步与互斥面向对象的解决方案(二))