• 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<BlockingQueue<Thread>> queueList=new ArrayList<BlockingQueue<Thread>>();

        //每一个信号量相应的堵塞队列

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

    this.semaphores=semaphores;

    for(int i=0;i<semaphores.length;i++){

    queueList.add(new LinkedBlockingQueue<Thread>());

    }

    }

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

    int semaphoreIndex=0;

    for(;semaphoreIndex<semaphores.length;semaphoreIndex++){//推断每一个条件是否都满足

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

    break;

    }

    }

    if(semaphoreIndex<semaphores.length-1){//条件不满足时

    queueList.get(semaphoreIndex).add(t);//加入到堵塞队列

    try {

    synchronized(t){       

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

    }

    } catch (Exception e) {

    }

    }else{

    for(semaphoreIndex=0;semaphoreIndex<semaphores.length;semaphoreIndex++){

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

    }

    }

    }

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

    for(int semaphoreIndex=0;semaphoreIndex<semaphores.length;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<BlockingQueue<Thread>> queueList=new ArrayList<BlockingQueue<Thread>>();

        private Map<Thread,Integer[]> map=new HashMap<Thread,Integer[]>();//保存第线程的请求

    public CollectPV(int[] semaphores) {

    this.semaphores=semaphores;

    for(int i=0;i<semaphores.length;i++){

    queueList.add(new LinkedBlockingQueue<Thread>());

    }

    }

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

    try {

    int semaphoreIndex=0;

    for(;semaphoreIndex<semaphores.length;semaphoreIndex++){

    if(semaphores[semaphoreIndex]<semas[semaphoreIndex]){

    break;

    }

    }

    if(semaphoreIndex<semaphores.length){

    BlockingQueue<Thread> 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.length;semaphoresIndex++){

         semaphores[semaphoresIndex]-=semas[semaphoresIndex];

    }

    }

    } catch (Exception e) {

    }

    }

    public synchronized void v(Integer[] semas){

    try {

    for(int semaphoreIndex=0;semaphoreIndex<semaphores.length;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) {

    }

    }

    }

    版权声明:本文博客原创文章。博客,未经同意,不得转载。

  • 相关阅读:
    string::push_back()
    string::pop_back
    string::insert
    string::get_allocator
    opencv —— minEnclosingCircle、fitEllipse 寻找包裹轮廓的最小圆、点集拟合椭圆
    opencv —— boundingRect、minAreaRect 寻找包裹轮廓的最小正矩形、最小斜矩形
    opencv —— approxPolyDP 生成逼近曲线
    opencv —— convexHull 寻找并绘制凸包
    opencv —— findContours、drawContours 寻找并绘制轮廓
    opencv —— equalizeHist 直方图均衡化实现对比度增强
  • 原文地址:https://www.cnblogs.com/lcchuguo/p/4742023.html
Copyright © 2020-2023  润新知