title: I am trying to implement a resource handler class. It must be deadlock-free and starvation-free
body: <p>It is a homework assignment. I have two files which were already given. The <code>Client class</code> and the <code>SharedValues Interface</code>. Here is the description:</p>
  
  <p>I need to write a <code>class</code> (resource handler) which contains <code>static interfaces</code> and manage "n" number of resource allocation and its scheduling for "k" number of clients. there must be only <code>two operations</code> for the clients. <code>Reading and writing</code> with <code>no deadlock and no starvation</code>. If one resource is allocated for writing then other clients can't have it for any other purpose. If the resource is allocated for reading then only readers can get it, writers not. A key can make the resources free it got for the allocation. The references of resources are represented by <code>String</code> (names).</p>
  
  <p>The <code>Resource Handler</code> must contain <code>two interfaces</code> for the clients. <code>getLock()</code> and <code>releaseLock()</code>. The required argument of the <code>getLock()</code> interface is an object <code>(Set&lt;String&gt;)</code> in which the names of the resources and the desired operations <code>(boolean: true - writing, false - reading)</code> are placed, the return value is an <code>identifier (long)</code>. Until the resource handler can't give the requested resources to the cleint, the resource handler should be blocked the current client on the <code>getLock()</code> call. It will be unblock again when the requested resources are available for the given operation. The return value of the <code>releaseLock()</code> is <code>void</code>, its required argument is an identifier what it got at the <code>getLock()</code> call. The clients are requesting the lock/release of resources as a subsets of resources from the resource handler class (through the <code>getLock()</code> interface) and the clients are releasing the resources by the received identifier. (through the <code>releaseLock()</code> interface).</p>
  
  <p>I am not pro in Java and i have only a little experience in multithreading. Please take into account.</p>
  
  <p><strong>Given the following class and interface:</strong></p>
  
  <p><strong>SharedValues Interface</strong></p>
  
  <pre><code>    public interface SharedValues
      {
          //resources
          public final static String[] RESOURCE_LIST = new String[]{ "a", "b", "c", "d", "e", "f", "g", "h" };
  
          //constant of the client's writing method type
          public final static boolean WRITE_METHOD = true;
  
          //constant of the client's reading method type
          public final static boolean READ_METHOD = false;
  
          //constant for the number of clients
          public final static int CLIENTNUM = 5;
  
          //minimum wait time of the client
          public final static int CLIENT_HOLD_MINIMUM = 1000;
  
          //maximum wait time difference of the client
          public final static int CLIENT_HOLD_DIFF = 1000;
  
          //time limit of the clients
          public final static int RUNTIME = 20000;
  }
  </code></pre>
  
  <p><strong>Client class</strong></p>
  
  <pre><code>import java.util.Arrays;
  import java.util.Collections;
  import java.util.Date;
  import java.util.HashSet;
  import java.util.Random;
  import java.util.Set;
  import java.util.ArrayList;
  
  //start and implementation of the client
  public class Client extends Thread implements SharedValues
  {
      //used random for creating clients
      private static Random mRandom = new Random();
  
      //for stoping flag
      private boolean mRunning = true;
  
      //used method in client
      private boolean mMethod = true;
  
      //the clients want to lock these resources
      private Set&lt;String&gt; mNeededRes = new HashSet&lt;String&gt;();
  
      //received identifier for the releasing cleint's resources
      private long mLockID = -1;
  
      //client's logging name
      private String mLogName = null;
  
      //client's constructor
      public Client( String[] xResList, boolean xMethod, int xClientID )
      {
          super( "Client_" + xClientID );
          mLogName = "Client_" + xClientID;
          mMethod = xMethod;
  
          for ( int i = 0; i &lt; xResList.length; i++ )
          {
              mNeededRes.add( xResList[ i ] );
          }
      }
  
      //interface for logging
      private void log( String xMessage )
      {
          System.out.println( new Date() + " " + mLogName + ": " + xMessage );
      }
  
      //holding resources or sleeping
      private synchronized void holdResources()
      {
          if ( !mRunning )
          {
              return;
          }
  
          //sleeping a value what is in the intervall
          try
          {
              wait( mRandom.nextInt( CLIENT_HOLD_DIFF ) &amp; CLIENT_HOLD_MINIMUM );
          }
          catch ( InterruptedException e )
          {
              log( "Error: Resource allocating interrupted" );
          }
      }
  
      //for stopping interface
      public synchronized void stopRunning() throws Exception
      {
          //changing the flag and interrupting the sleep if it has
          if ( mRunning )
          {
              mRunning = false;
              wait();
          }
          else
          {
              log( "Error: the client has already stopped!" );
          }
      }
  
      //Overloading thread method
      public void run()
      {
          log( "Started." );
  
          while ( mRunning )
          {
              log( ( ( mMethod == WRITE_METHOD ) ? "Writing" : "Reading" ) + " requested resources: "
                  + toSortedSet( mNeededRes ) );
  
              final long startTime = System.currentTimeMillis();
              mLockID = ResHandler.getLock( mNeededRes, mMethod );
              final long elapsed = System.currentTimeMillis() - startTime;
  
              log( ( ( mMethod == WRITE_METHOD ) ? "Writing" : "Reading" ) + " received resources (" + elapsed
                  + " ms): " + toSortedSet( mNeededRes ) + ". Lock: " + mLockID );
  
              holdResources();
  
              ResHandler.releaseLock( mLockID );
  
              holdResources();
          }
  
          log( "Stopped." );
      }
  
      //creating clients
      private static Client createClient( int xClientID )
      {
          final int resNum = mRandom.nextInt( RESOURCE_LIST.length ) + 1;
  
          //randomly take out one of all resources
          final ArrayList&lt;String&gt; selectedRes = new ArrayList&lt;String&gt;( Arrays.asList( RESOURCE_LIST ) );
  
          for ( int i = 0; i &lt; ( RESOURCE_LIST.length - resNum ); i++ )
          {
              final int chosenRes = mRandom.nextInt( selectedRes.size() );
  
              selectedRes.remove( chosenRes );
          }
  
          final boolean method = mRandom.nextInt( 5 ) &lt;= 2;
  
          return new Client( ( String[] ) selectedRes.toArray( new String[]{} ), method, xClientID );
      }
  
      //auxiliary interface for elements of subset, we can do sorted logging
      private String toSortedSet( Set&lt;String&gt; xSet )
      {
          final StringBuffer tmpSB = new StringBuffer( "{ " );
  
          final String[] sortedRes = ( String[] ) xSet.toArray( new String[]{} );
          Arrays.sort( sortedRes );
  
          for ( int i = 0; i &lt; sortedRes.length; i++ )
          {
              tmpSB.append( sortedRes[ i ] ).append( ", " );
          }
          tmpSB.setLength( tmpSB.length() - 2 );
          tmpSB.append( " }" );
  
          return tmpSB.toString();
      }
  
      public static void main( String[] args ) throws Exception
      {
          //keep the clients for stop
          final Client[] clientArr = new Client[ CLIENTNUM ];
  
          for ( int i = 0; i &lt; clientArr.length; i++ )
          {
              clientArr[ i ] = createClient( i );
              clientArr[ i ].start();
  
              //the clients do not start at the same time
              try
              {
                  Thread.sleep( mRandom.nextInt( CLIENT_HOLD_MINIMUM ) );
              }
              catch ( InterruptedException e )
              {
                  e.printStackTrace();
              }
          }
  
          //sleeping the running time of clients
          try
          {
              Thread.sleep( RUNTIME );
          }
          catch ( InterruptedException e )
          {
              e.printStackTrace();
          }
  
          //stopping cleints
          for ( int i = 0; i &lt; clientArr.length; i++ )
          {
              clientArr[ i ].stopRunning();
  
              try
              {
                  clientArr[ i ].join();
              }
              catch ( InterruptedException e )
              {
                  e.printStackTrace();
              }
          }
      }
  }
  </code></pre>
  
  <p>I wrote this so far. I see the client log where the Lock is always 0 and the elapsed time 0ms but I do not know why.</p>
  
  <p><strong>Resource Handler class</strong></p>
  
  <pre><code>import java.util.Set;
  
  
      class ResHandler {
  
          private static long identifier;
  
          public static long getLock(Set&lt;String&gt; mNeededRes, boolean mMethod) {
  
              return identifier;
          }
  
  
          public static void releaseLock(long mLockID) {
  
          } 
  </code></pre>
  
  <p><strong>This is the Output:</strong></p>
  
  <pre><code> Wed Oct 09 04:42:25 CEST 2013 Client_0: Started.
  
  Wed Oct 09 04:42:25 CEST 2013 Client_0: Writing requested resources: { b, c, d, g, h }
  
  Wed Oct 09 04:42:25 CEST 2013 Client_0: Writing received resources (4 ms): { b, c, d, g, h }. Lock: 0
  
  Wed Oct 09 04:42:26 CEST 2013 Client_1: Started.
  
  Wed Oct 09 04:42:26 CEST 2013 Client_1: Writing requested resources: { a, b, c, d, e, f, g, h }
  
  Wed Oct 09 04:42:26 CEST 2013 Client_1: Writing received resources (0 ms): { a, b, c, d, e, f, g, h }. Lock: 0
  
  Wed Oct 09 04:42:26 CEST 2013 Client_0: Writing requested resources: { b, c, d, g, h }
  
  Wed Oct 09 04:42:26 CEST 2013 Client_0: Writing received resources (0 ms): { b, c, d, g, h }. Lock: 0
  
  Wed Oct 09 04:42:26 CEST 2013 Client_1: Writing requested resources: { a, b, c, d, e, f, g, h }
  
  Wed Oct 09 04:42:26 CEST 2013 Client_1: Writing received resources (0 ms): { a, b, c, d, e, f, g, h }. Lock: 0
  
  Wed Oct 09 04:42:26 CEST 2013 Client_2: Started.
  
  Wed Oct 09 04:42:26 CEST 2013 Client_2: Writing requested resources: { a, b, d, e, f, g, h }
  
  Wed Oct 09 04:42:26 CEST 2013 Client_2: Writing received resourcesk (0 ms): { a, b, d, e, f, g, h }. Lock: 0
  
  Wed Oct 09 04:42:27 CEST 2013 Client_0: Writing requested resources: { b, c, d, g, h }
  
  Wed Oct 09 04:42:27 CEST 2013 Client_0: Writing received resources (0 ms): { b, c, d, g, h }. Lock: 0
  
  Wed Oct 09 04:42:27 CEST 2013 Client_3: Started.
  
  Wed Oct 09 04:42:27 CEST 2013 Client_3: Reading requested resources: { a, b, c, d, e, f, g, h }
  
  Wed Oct 09 04:42:27 CEST 2013 Client_3: Reading received resources (0 ms): { a, b, c, d, e, f, g, h }. Lock: 0
  
  Wed Oct 09 04:42:27 CEST 2013 Client_4: Started.
  
  Wed Oct 09 04:42:27 CEST 2013 Client_4: Reading requested resources: { f, h }
  
  Wed Oct 09 04:42:27 CEST 2013 Client_4: Reading received resources (0 ms): { f, h }. Lock: 0
  
  Wed Oct 09 04:42:27 CEST 2013 Client_1: Writing requested resources: { a, b, c, d, e, f, g, h }
  
  Wed Oct 09 04:42:27 CEST 2013 Client_1: Writing received resources (0 ms): { a, b, c, d, e, f, g, h }. Lock: 0
  
  Wed Oct 09 04:42:28 CEST 2013 Client_0: Writing requested resources: { b, c, d, g, h }
  
  Wed Oct 09 04:42:28 CEST 2013 Client_0: Writing received resources (0 ms): { b, c, d, g, h }. Lock: 0
  
  Wed Oct 09 04:42:28 CEST 2013 Client_4: Reading requested resources: { f, h }
  
  Wed Oct 09 04:42:28 CEST 2013 Client_4: Reading received resources (0 ms): { f, h }. Lock: 0
  
  Wed Oct 09 04:42:28 CEST 2013 Client_3: Reading requested resources: { a, b, c, d, e, f, g, h }
  
  Wed Oct 09 04:42:28 CEST 2013 Client_3: Reading received resources (0 ms): { a, b, c, d, e, f, g, h }. Lock: 0
  
  Wed Oct 09 04:42:28 CEST 2013 Client_2: Writing requested resources: { a, b, d, e, f, g, h }
  
  Wed Oct 09 04:42:28 CEST 2013 Client_2: Writing received resources (0 ms): { a, b, d, e, f, g, h }. Lock: 0
  
  Wed Oct 09 04:42:28 CEST 2013 Client_3: Reading requested resources: { a, b, c, d, e, f, g, h }
  
  Wed Oct 09 04:42:28 CEST 2013 Client_3: Reading received resources (0 ms): { a, b, c, d, e, f, g, h }. Lock: 0
  
  Wed Oct 09 04:42:29 CEST 2013 Client_1: Writing requested resources: { a, b, c, d, e, f, g, h }
  
  Wed Oct 09 04:42:29 CEST 2013 Client_1: Writing received resources (0 ms): { a, b, c, d, e, f, g, h }. Lock: 0
  
  Wed Oct 09 04:42:29 CEST 2013 Client_2: Writing requested resources: { a, b, d, e, f, g, h }
  
  Wed Oct 09 04:42:29 CEST 2013 Client_2: Writing received resources (0 ms): { a, b, d, e, f, g, h }. Lock: 0
  
  Wed Oct 09 04:42:29 CEST 2013 Client_4: Reading requested resources: { f, h }
  
  Wed Oct 09 04:42:29 CEST 2013 Client_4: Reading received resources (0 ms): { f, h }. Lock: 0
  
  Wed Oct 09 04:42:29 CEST 2013 Client_0: Writing requested resources: { b, c, d, g, h }
  
  Wed Oct 09 04:42:29 CEST 2013 Client_0: Writing received resources (0 ms): { b, c, d, g, h }. Lock: 0
  </code></pre>
  
  <p>. . .</p>
  
  <p><strong>I found a half solution on the internet:</strong> 
  <a href="https://stackoverflow.com/questions/16253593/resource-manager-with-reentrantlocks">Resource manager with ReentrantLocks</a></p>
  
  <pre><code>public class ResHandler {
  
  //ID-s of the granted resource lists
  private static long lockNum = 0;
  
  //Resources are identified by strings, each client has a list of demanded resources
  //we store these when granted, along with an ID
  private static ConcurrentHashMap&lt;Long, Set&lt;String&gt;&gt; usedResources 
      = new ConcurrentHashMap&lt;Long, Set&lt;String&gt;&gt;();
  
  //We store a lock for each resource
  private static ConcurrentHashMap&lt;String, ReentrantReadWriteLock&gt; resources 
      = new ConcurrentHashMap&lt;String, ReentrantReadWriteLock&gt;();
  
  //Filling our resources map with the resources and their locks
  static {
      for (int i = 0; i &lt; SharedValues.RESOURCE_LIST.length; ++i) {
          String res = SharedValues.RESOURCE_LIST[i];
          //Fair reentrant lock
          ReentrantReadWriteLock lc = new ReentrantReadWriteLock(true);
          resources.put(res, lc);
      }
  }
  
  //We get a set of the required resources and the type of lock we have to use
  public static long getLock(Set&lt;String&gt; mNeededRes, boolean mMethod) {
      //!!!
      if (mMethod == SharedValues.READ_METHOD) {
  
          //We try to get the required resources
          for (String mn : mNeededRes)
              resources.get(mn).readLock().lock();
  
          //After grandted, we put them in the usedResources map
          ++lockNum;
          usedResources.put(lockNum, mNeededRes);
          return lockNum;         
      }
  
      //Same thing, but with write locks
      else {
  
          for (String mn : mNeededRes)
              resources.get(mn).writeLock().lock();
  
          ++lockNum;
          usedResources.put(lockNum, mNeededRes);
          return lockNum;         
      }
  }
  
  //Releasing a set of locks by the set's ID
  public static void releaseLock(long mLockID) {
      if (!usedResources.containsKey(mLockID)) {
          System.out.println("returned, no such key as: " + mLockID);
          return; 
      }
  
      Set&lt;String&gt; toBeReleased = usedResources.get(mLockID);
  
      //Unlocking every lock from this set
      for (String s : toBeReleased) {
          if (resources.get(s).isWriteLockedByCurrentThread())
              resources.get(s).writeLock().unlock();
          else 
              resources.get(s).readLock().unlock();
      }
  
      //Deleting from the map
      usedResources.remove(mLockID);
  }   
  }
  </code></pre>
  
  <p><strong>I tried this and the output was changed to this:</strong></p>
  
  <pre><code>Fri Oct 11 10:14:40 CEST 2013 Client_0: Started.
  
  Fri Oct 11 10:14:40 CEST 2013 Client_0: Reading requested resources: { b, c, h }
  
  Fri Oct 11 10:14:40 CEST 2013 Client_0: Reading received resources (8 ms): { b, c, h }. Lock: 1
  
  Fri Oct 11 10:14:40 CEST 2013 Client_1: Started.
  
  Fri Oct 11 10:14:40 CEST 2013 Client_1: Reading requested resources: { a, b, c, d, f, g, h }
  
  Fri Oct 11 10:14:40 CEST 2013 Client_1: Reading received resources (1 ms): { a, b, c, d, f, g, h }. Lock: 2
  
  Fri Oct 11 10:14:40 CEST 2013 Client_2: Started.
  
  Fri Oct 11 10:14:40 CEST 2013 Client_2: Reading requested resources: { a, b, d, e, f, g, h }
  
  Fri Oct 11 10:14:40 CEST 2013 Client_2: Reading received resources (0 ms): { a, b, d, e, f, g, h }. Lock: 3
  
  Fri Oct 11 10:14:40 CEST 2013 Client_2: Reading requested resources: { a, b, d, e, f, g, h }
  
  Fri Oct 11 10:14:40 CEST 2013 Client_2: Reading received resources (0 ms): { a, b, d, e, f, g, h }. Lock: 4
  
  Fri Oct 11 10:14:41 CEST 2013 Client_3: Started.
  
  Fri Oct 11 10:14:41 CEST 2013 Client_3: Writing requested resources: { h }
  
  Fri Oct 11 10:14:41 CEST 2013 Client_1: Reading requested resources: { a, b, c, d, f, g, h }
  
  Fri Oct 11 10:14:41 CEST 2013 Client_0: Reading requested resources: { b, c, h }
  
  Fri Oct 11 10:14:41 CEST 2013 Client_3: Writing received resources (303 ms): { h }. Lock: 5
  
  Fri Oct 11 10:14:41 CEST 2013 Client_1: Reading received resources (293 ms): { a, b, c, d, f, g, h }. Lock: 6
  
  Fri Oct 11 10:14:41 CEST 2013 Client_0: Reading received resources (171 ms): { b, c, h }. Lock: 7
  
  Fri Oct 11 10:14:41 CEST 2013 Client_3: Writing requested resources: { h }
  
  Fri Oct 11 10:14:41 CEST 2013 Client_4: Started.
  
  Fri Oct 11 10:14:41 CEST 2013 Client_4: Reading requested resources: { a, b, c, d, e, f, g, h }
  
  Fri Oct 11 10:14:42 CEST 2013 Client_3: Writing received resources (633 ms): { h }. Lock: 8
  
  Fri Oct 11 10:14:42 CEST 2013 Client_2: Reading requested resources: { a, b, d, e, f, g, h }
  
  Fri Oct 11 10:14:42 CEST 2013 Client_4: Reading received resources (819 ms): { a, b, c, d, e, f, g, h }. Lock: 9
  
  Fri Oct 11 10:14:42 CEST 2013 Client_2: Reading received resources (163 ms): { a, b, d, e, f, g, h }. Lock: 10
  
  Fri Oct 11 10:14:42 CEST 2013 Client_1: Reading requested resources: { a, b, c, d, f, g, h }
  
  Fri Oct 11 10:14:42 CEST 2013 Client_1: Reading received resourcesk (0 ms): { a, b, c, d, f, g, h }. Lock: 11
  
  Fri Oct 11 10:14:42 CEST 2013 Client_0: Reading requested resources: { b, c, h }
  
  Fri Oct 11 10:14:42 CEST 2013 Client_0: Reading received resources (0 ms): { b, c, h }. Lock: 12
  
  Fri Oct 11 10:14:42 CEST 2013 Client_3: Writing requested resources: { h }
  
  Fri Oct 11 10:14:42 CEST 2013 Client_0: Reading requested resources: { b, c, h }
  
  Fri Oct 11 10:14:43 CEST 2013 Client_1: Reading requested resources: { a, b, c, d, f, g, h }
  
  Fri Oct 11 10:14:43 CEST 2013 Client_3: Writing received resources (447 ms): { h }. Lock: 13
  
  Fri Oct 11 10:14:43 CEST 2013 Client_0: Reading received resources (504 ms): { b, c, h }. Lock: 14
  
  Fri Oct 11 10:14:43 CEST 2013 Client_1: Reading received resources (210 ms): { a, b, c, d, f, g, h }. Lock: 15
  
  Fri Oct 11 10:14:43 CEST 2013 Client_4: Reading requested resources: { a, b, c, d, e, f, g, h }
  
  Fri Oct 11 10:14:43 CEST 2013 Client_4: Reading received resources (0 ms): { a, b, c, d, e, f, g, h }. Lock: 16
  
  Fri Oct 11 10:14:43 CEST 2013 Client_2: Reading requested resources: { a, b, d, e, f, g, h }
  
  Fri Oct 11 10:14:43 CEST 2013 Client_2: Reading received resources (0 ms): { a, b, d, e, f, g, h }. Lock: 17
  
  Fri Oct 11 10:14:43 CEST 2013 Client_1: Reading requested resources: { a, b, c, d, f, g, h }
  
  Fri Oct 11 10:14:43 CEST 2013 Client_1: Reading received resources (0 ms): { a, b, c, d, f, g, h }. Lock: 18
  
  Fri Oct 11 10:14:44 CEST 2013 Client_3: Writing requested resources: { h }
  
  Fri Oct 11 10:14:44 CEST 2013 Client_3: Writing received resources (152 ms): { h }. Lock: 19
  
  Fri Oct 11 10:14:44 CEST 2013 Client_2: Reading requested resources: { a, b, d, e, f, g, h }
  
  Fri Oct 11 10:14:44 CEST 2013 Client_0: Reading requested resources: { b, c, h }
  
  Fri Oct 11 10:14:44 CEST 2013 Client_4: Reading requested resources: { a, b, c, d, e, f, g, h }
  
  Fri Oct 11 10:14:44 CEST 2013 Client_1: Reading requested resources: { a, b, c, d, f, g, h }
  
  Fri Oct 11 10:14:45 CEST 2013 Client_0: Reading received resources (504 ms): { b, c, h }. Lock: 21
  
  Fri Oct 11 10:14:45 CEST 2013 Client_4: Reading received resources (399 ms): { a, b, c, d, e, f, g, h }. Lock: 22
  
  Fri Oct 11 10:14:45 CEST 2013 Client_1: Reading received resources (230 ms): { a, b, c, d, f, g, h }. Lock: 23
  
  Fri Oct 11 10:14:45 CEST 2013 Client_2: Reading received resources (544 ms): { a, b, d, e, f, g, h }. Lock: 20
  
  Fri Oct 11 10:14:45 CEST 2013 Client_1: Reading requested resources: { a, b, c, d, f, g, h }
  
  Fri Oct 11 10:14:45 CEST 2013 Client_1: Reading received resources (0 ms): { a, b, c, d, f, g, h }. Lock: 24
  
  Fri Oct 11 10:14:45 CEST 2013 Client_3: Writing requested resources: { h }
  
  Fri Oct 11 10:14:45 CEST 2013 Client_2: Reading requested resources: { a, b, d, e, f, g, h }
  
  Fri Oct 11 10:14:45 CEST 2013 Client_0: Reading requested resources: { b, c, h }
  
  Fri Oct 11 10:14:46 CEST 2013 Client_4: Reading requested resources: { a, b, c, d, e, f, g, h }
  </code></pre>
  
  <p>but here the program is frozen. I guess because of deadlock. </p>
  
  <p>My question is: How can I fix this. I would really really apreciate if somebody could show me some working code example. </p>