import java.util.Deque;
import java.util.ArrayDeque;

public class Semaphore {
  private int value;
  private Deque<Long> locks = new ArrayDeque<>();
  // private Object lock = new Object();

  // private class Lock {
  //   // public Object lock;
  //   public int value;
  //
  //   public Lock(int value) {
  //     // this.lock = new Object();
  //     this.value = value;
  //   }
  // }

  public Semaphore() {
    this.value = 1;
  }

  public Semaphore(int value) {
    this.value = value;
  }

  public void P() {
    P(1);
  }

  public void V() {
    V(1);
  }

  public synchronized void P(int units) {
    synchronized (this) {
      Long lock = Thread.currentThread().getId();
      locks.addLast(lock);

      while (units > value || (!locks.isEmpty() && locks.getFirst() != lock)) {
        try {
          wait();
        } catch (InterruptedException e) {
          e.printStackTrace();
          Thread.currentThread().interrupt();
        }
      }

      value -= units;
      if (!locks.isEmpty())
        locks.removeFirst(); //remove this thread's object (== remove(obj)) TODO ?
      notifyAll();
    }
  }

  public synchronized void V(int units) {

    synchronized (this) {
      value += units;
      notifyAll();
    }
}

  // private synchronized void addLast(Lock lock) {
  //   locks.addLast(lock);
  // }
  // private synchronized Lock getFirst() {
  //   return locks.getFirst();
  // }
  // private synchronized Lock removeFirst() {
  //   return locks.removeFirst();
  // }



	public int getValue() {
		return value;
	}
}

@@ -111,18 +111,18 @@
 Deque%3CLo
-ng
+ck
 %3E locks 
@@ -184,21 +184,38 @@
 ject();%0A
-%0A  //
+  public int wakes;%0A%0A 
  private
@@ -229,19 +229,16 @@
 Lock %7B%0A 
- //
    // pu
@@ -256,19 +256,16 @@
  lock;%0A 
- //
    publi
@@ -281,17 +281,10 @@
 ue;%0A
+%0A
  
- //%0A  //
    p
@@ -298,25 +298,13 @@
 ock(
-int value
 ) %7B%0A 
- //
     
@@ -339,14 +339,14 @@
 ;%0A  
-//
     
+//
  thi
@@ -367,20 +367,14 @@
 e;%0A 
- //
    %7D%0A 
- //
  %7D%0A%0A
@@ -557,37 +557,24 @@
 %7D%0A%0A  public 
-synchronized 
 void P(int u
@@ -577,24 +577,40 @@
 nt units) %7B%0A
+    Lock lock;%0A%0A
     synchron
@@ -633,48 +633,23 @@
     
-Long 
 lock = 
-Thread.currentThread().getId
+new Lock
 ();%0A
@@ -675,16 +675,47 @@
 (lock);%0A
+    %7D%0A%0A    synchronized(lock) %7B
 %0A      w
@@ -815,16 +815,21 @@
     
+lock.
 wait();%0A
     
@@ -820,24 +820,43 @@
 ock.wait();%0A
+          ++wakes;%0A
         %7D ca
@@ -977,24 +977,56 @@
   %7D%0A      %7D%0A
+    %7D%0A%0A    synchronized (this) %7B
 %0A      value
@@ -1041,16 +1041,19 @@
 s;%0A     
+ //
  if (!lo
@@ -1087,22 +1087,21 @@
 s.remove
-First(
+(lock
 ); //rem
@@ -1155,35 +1155,37 @@
 ?%0A      
-notifyAll()
+  lock = null
 ;%0A    %7D%0A
   %7D%0A%0A  p
@@ -1180,34 +1180,169 @@
   %7D%0A
+%0A
   
-%7D%0A%0A  public synchronized
+  if (!locks.isEmpty())%0A      lock = locks.getFirst();%0A%0A    if (lock != null) %7B%0A      synchronized (lock) %7B%0A        lock.notify();%0A      %7D%0A    %7D%0A  %7D%0A%0A  public
  voi
@@ -1357,16 +1357,31 @@
 units) %7B
+%0A    Lock lock;
 %0A%0A    sy
@@ -1432,17 +1432,140 @@
     
+if (!locks.isEmpty())%0A        lock = locks.getFirst();%0A      else%0A        return;%0A    %7D%0A%0A    synchronized (lock) %7B%0A      lock.
 notify
-All
 ();%0A

Implement fair semaphore with notify()