View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.transaction.locking;
18  
19  import org.apache.commons.transaction.util.LoggerFacade;
20  
21  /**
22   * Convenience implementation of a read/write lock based on {@link GenericLock}.
23   * <br>
24   * <br>
25   * Reads are shared which means there can be any number of concurrent read
26   * accesses allowed by this lock. Writes are exclusive. This means when there is
27   * a write access no other access neither read nor write are allowed by this
28   * lock. Additionally, writes are preferred over reads in order to avoid starvation. The idea
29   * is that there are many readers, but few writers and if things work out bad the writer would
30   * never be served at all. That's why it is preferred.<br>
31   * <br>
32   * Calls to both {@link #acquireRead(Object, long)}and
33   * {@link #acquireWrite(Object, long)}are blocking and reentrant. Blocking
34   * means they will wait if they can not acquire the descired access, reentrant means that a lock
35   * request by a specific owner will always be compatible with other accesses on this lock by the
36   * same owner. E.g. if you already have a lock for writing and you try to acquire write access 
37   * again you will not be blocked by this first lock, while others of course will be. This is the
38   * natural way you already know from Java monitors and synchronized blocks.
39   * 
40   * @version $Id: ReadWriteLock.java 493628 2007-01-07 01:42:48Z joerg $
41   * @see GenericLock
42   */
43  public class ReadWriteLock extends GenericLock {
44  
45      public static final int NO_LOCK = 0;
46  
47      public static final int READ_LOCK = 1;
48  
49      public static final int WRITE_LOCK = 2;
50  
51      /**
52       * Creates a new read/write lock.
53       * 
54       * @param resourceId
55       *            identifier for the resource associated to this lock
56       * @param logger
57       *            generic logger used for all kind of debug logging
58       */
59      public ReadWriteLock(Object resourceId, LoggerFacade logger) {
60          super(resourceId, WRITE_LOCK, logger);
61      }
62  
63      /**
64       * Tries to acquire a blocking, reentrant read lock. A read lock is
65       * compatible with other read locks, but not with a write lock.
66       * 
67       * @param ownerId
68       *            a unique id identifying the entity that wants to acquire a
69       *            certain lock level on this lock
70       * @param timeoutMSecs
71       *            if blocking is enabled by the <code>wait</code> parameter
72       *            this specifies the maximum wait time in milliseconds
73       * @return <code>true</code> if the lock actually was acquired
74       * @throws InterruptedException
75       *             when the thread waiting on this method is interrupted
76       */
77      public boolean acquireRead(Object ownerId, long timeoutMSecs) throws InterruptedException {
78          return acquire(ownerId, READ_LOCK, false, timeoutMSecs);
79      }
80  
81      /**
82       * Tries to acquire a blocking, reentrant write lock. A write lock is
83       * incompatible with any another read or write lock and is thus exclusive.
84       * 
85       * @param ownerId
86       *            a unique id identifying the entity that wants to acquire a
87       *            certain lock level on this lock
88       * @param timeoutMSecs
89       *            if blocking is enabled by the <code>wait</code> parameter
90       *            this specifies the maximum wait time in milliseconds
91       * @return <code>true</code> if the lock actually was acquired
92       * @throws InterruptedException
93       *             when the thread waiting on this method is interrupted
94       */
95      public boolean acquireWrite(Object ownerId, long timeoutMSecs) throws InterruptedException {
96          return acquire(ownerId, WRITE_LOCK, true, timeoutMSecs);
97      }
98  }