信号量:具有优先级的关键部分

时间:2012-04-10 04:31:07

标签: java synchronization semaphore critical-section

我正在用Java编写一个程序来处理Semaphores的任务。我对Semaphores和并发的想法还很陌生。 问题的描述如下:

  1. 布尔的向量V []。如果Pi需要使用临界区,则V [i]为“True”。
  2. 二进制信号量B []的向量,用于阻止进入其临界区的进程:B [i]将成为信号量阻塞进程Pi。
  3. 只要需要唤醒被阻止的进程以使用关键部分,就会使用特殊的调度程序进程SCHED。
  4. 等待特殊信号量S
  5. 阻止SCHED
  6. 当进程Pi需要进入临界区时,它将V [i]设置为“True”,发出信号量S的信号,然后等待信号量B [i]。
  7. 每当SCHED被解锁时,它选择具有最小索引i的过程Pi,其中V [i]为“真”。然后通过发信号B [i]唤醒进程Pi,并且SCHED通过阻塞信号量S重新进入休眠状态。
  8. 当一个过程Pi离开临界区时,它会发出信号S.
  9. 这是我的代码:

    import java.util.concurrent.Semaphore;
    
    public class Process extends Thread {
        static boolean V[];
        int i;
        static Semaphore B[]; //blocking semaphore
        static Semaphore S;
        private static int id;
        static int N;
        static int insist = 0;
    
        public static void process (int i, int n) {
           id = i;
           N = n;
           V = new boolean[N];
        }
    
        private void delay () {
           try {
            sleep (random(500));
            }
            catch (InterruptedException p) {
            }
        }
    
        private static int random(int n) {
            return (int) Math.round(n * Math.random() - 0.5);
        }
    
        private void entryprotocol(int i) {
             V[Process.id] = true;
             int turn = N;
             while (V[Process.id] == true && turn == N) {
               System.out.println("P" + Process.id + " is requesting critical section");
               signal(S);
             }
            critical(Process.id);
            wait(B[Process.id]);
            V[Process.id] = false;
            }
    
    
    
       private void wait(Semaphore S) {
           if (Process.id > 0) {
            Process.id--;
          } else {
            //add Process.id to id.queue and block
            wait(B[Process.id]);
           }
       }
    
         private void signal(Semaphore S) {
             if (B[Process.id] != null) {
              Sched(Process.id);
            } else {
              Process.id++; //remove process from queue
              critical(Process.id); //wakes up current process
             }
         }
    
        private void critical(int i) {
            System.out.println("P" + Process.id + " is in the critical section");
            delay();
            exitprotocol(i);
         }
    
        private void exitprotocol(int i) {
            System.out.println("P" + Process.id + " is leaving the critical section");
            V[id] = false;
            signal(S);
        }
    
         public void Sched(int i) {
             if (B[Process.id] == null) {
            signal(B[Process.id]);
            }
            wait(S);
         }
    
         public void run() {
             for (int i = 0; i < 5; i++) {
                Sched(i);
               entryprotocol(Process.id);
               try {
                  wait(Process.id);
              }
               catch (InterruptedException p) {
                }
              signal(S);
            }
             }
    
    
        public static void main (String[] args) {
            int N = 5;
    
            Process p[] = new Process[N];
    
            for (int i = 0; i < N; i++) {
            p[i] = new Process();
            p[i].start();
            }
            }
       }
    

    我相信我的逻辑是正确的,但是我遇到了很多错误(比如线程“Thread-1”中的异常java.lang.NullPointerException)。任何人都可以解释我做错了什么吗?给我一些帮助。非常感谢!

1 个答案:

答案 0 :(得分:4)

您的NPE可能是因为您从未初始化您的信号量数组 - 但如果没有正确的堆栈跟踪,很难说。

两条建议:

1)您可能希望为您的类变量赋予比以下更有意义的名称:     乙     ñ     小号     V. 想象一下,离开这个项目并在4个月内重新审视它,并且必须仔细阅读。

2)在编写任何代码之前,在白板上找出你的班级模型。您有一些方法可以使用与某些静态字段同名的信号量。程序中对象的关系是什么?如果你不知道,你的程序也不知道。