Package org.apache.ignite

## Interface IgniteLock

- All Superinterfaces:
    `AutoCloseable`, `Closeable`, `Lock`

      public interface IgniteLock
      extends Lock, Closeable

  This interface provides a rich API for working with distributed reentrant locks.

  # Functionality

  Distributed reentrant lock provides functionality similar to `java.util.concurrent.ReentrantLock`.

  # Creating Distributed ReentrantLock

  Instance of cache reentrant lock can be created by calling the following method: `Ignite.reentrantLock(String, boolean, boolean, boolean)`.

  # Protection from failover

  Ignite lock can automatically recover from node failure.
  - If failoverSafe flag is set to true upon creation, in case a node owning the lock fails, lock will be automatically released and become available for threads on other nodes to acquire. No exception will be thrown.
  - If failoverSafe flag is set to false upon creation, in case a node owning the lock fails, `IgniteException` will be thrown on every other node attempting to perform any operation on this lock. No automatic recovery will be attempted, and lock will be marked as broken (i.e. unusable), which can be checked using the method #isBroken(). Broken lock cannot be reused again.

  # Implementation issues

  Ignite lock comes in two flavours: fair and non-fair. Non-fair lock assumes no ordering should be imposed on acquiring threads; in case of contention, threads from all nodes compete for the lock once the lock is released. In most cases this is the desired behaviour. However, in some cases, using the non-fair lock can lead to uneven load distribution among nodes. Fair lock solves this issue by imposing strict FIFO ordering policy at a cost of an additional transaction. This ordering does not guarantee fairness of thread scheduling (similar to `java.util.concurrent.ReentrantLock`). Thus, one of many threads on any node using a fair lock may obtain it multiple times in succession while other active threads are not progressing and not currently holding the lock. Also note that the untimed tryLock method does not honor the fairness setting. It will succeed if the lock is available even if other threads are waiting. As a rule of thumb, whenever there is a reasonable time window between successive calls to release and acquire the lock, non-fair lock should be preferred:

            while(someCondition){
                // do anything
                lock.lock();
                try{
                    // ...
                }
                finally {
                    lock.unlock();
                }
            }

  If successive calls to release/acquire are following immediately, e.g.

            while(someCondition){
                lock.lock();
                try {
                    // do something
                }
                finally {
                    lock.unlock();
                }
            }

  using the fair lock is reasonable in order to allow even distribution of load among nodes (although overall throughput may be lower due to increased overhead).

- - ### Method Summary

    All Methods Instance Methods Abstract Methods
    Modifier and Type | Method | Description
    --- | --- | ---
    `void` | `close()` | Removes reentrant lock.
    `int` | `getHoldCount()` | Queries the number of holds on this lock by the current thread.
    `IgniteCondition` | `getOrCreateCondition​(String name)` | Returns a `Condition` instance for use with this `IgniteLock` instance.
    `int` | `getWaitQueueLength​(IgniteCondition condition)` | Returns an estimate of the number of threads on this node that are waiting on the given condition associated with this lock.
    `boolean` | `hasQueuedThread​(Thread thread)` | Queries whether the given thread is waiting to acquire this lock.
    `boolean` | `hasQueuedThreads()` | Queries whether any threads on this node are waiting to acquire this lock.
    `boolean` | `hasWaiters​(IgniteCondition condition)` | Queries whether any threads on this node are waiting on the given condition associated with this lock.
    `boolean` | `isBroken()` | Returns true if any node that owned the locked failed before releasing the lock.
    `boolean` | `isFailoverSafe()` | Returns `true` if this lock is safe to use after node failure.
    `boolean` | `isFair()` | Returns `true` if this lock is fair.
    `boolean` | `isHeldByCurrentThread()` | Queries if this lock is held by the current thread.
    `boolean` | `isLocked()` | Queries if this lock is held by any thread on any node.
    `void` | `lock()` | Acquires the distributed reentrant lock.
    `void` | `lockInterruptibly()` | Acquires the lock unless the current thread is interrupted.
    `String` | `name()` | Name of atomic reentrant lock.
    `Condition` | `newCondition()` | This method is not supported in IgniteLock, Any invocation of this method will result in UnsupportedOperationException.
    `boolean` | `removed()` | Gets status of reentrant lock.
    `boolean` | `tryLock()` | Acquires the lock only if it is free at the time of invocation.
    `boolean` | `tryLock​(long timeout, TimeUnit unit)` | Acquires the lock if it is not held by another thread within the given waiting time and the current thread has not been interrupted.
    `void` | `unlock()` | Releases the lock.

- - ### Method Detail

    - #### name

          String name()

      Name of atomic reentrant lock.
      Returns:
        Name of atomic reentrant lock.

    - #### lock

          void lock()
             throws IgniteException

      Acquires the distributed reentrant lock.

      Acquires the lock if it is not held by another thread and returns immediately, setting the lock hold count to one.

      If the current thread already holds this lock then the hold count is incremented by one and the method returns immediately.

      If the lock is held by another thread then the current thread becomes disabled for thread scheduling purposes and lies dormant until one of four things happens:

      - The lock is acquired by the current thread; or
      - Lock is broken (any node failed while owning this lock), and lock is created in non-failoverSafe mode.
      - Local node is stopped.
      Specified by:
        `lock` in interface `Lock`
      Throws:
        `IgniteException` - if the node is stopped or broken in non-failoverSafe mode

    - #### lockInterruptibly

          void lockInterruptibly()
                          throws IgniteInterruptedException,
                                 IgniteException

      Acquires the lock unless the current thread is interrupted.

      Acquires the lock if it is not held by another thread and returns immediately, setting the lock hold count to one.

      If the current thread already holds this lock then the hold count is incremented by one and the method returns immediately.

      If the lock is held by another thread then the current thread becomes disabled for thread scheduling purposes and lies dormant until one of four things happens:

      - The lock is acquired by the current thread; or
      - Some other thread interrupts the current thread.
      - Lock is broken (any node failed while owning this lock), and lock is created in non-failoverSafe mode.
      - Local node is stopped.

      If the lock is acquired by the current thread then the lock hold count is set to one.

      If the current thread:

      - has its interrupted status set on entry to this method; or
      - is interrupted while acquiring the lock; or then `IgniteInterruptedException` is thrown and the current thread's interrupted status is cleared.

      `IgniteException` is thrown in case:

      - the lock is broken before or during the attempt to acquire this lock; or
      - local node is stopped,

      In this implementation, as this method is an explicit interruption point, preference is given to responding to the interrupt over normal or reentrant acquisition of the lock.

      Specified by:
        `lockInterruptibly` in interface `Lock`
      Throws:
        `IgniteInterruptedException` - if the current thread is interrupted
        `IgniteException` - if the lock is broken in non-failoverSafe mode (any node failed while owning this lock), or local node is stopped

    - #### tryLock

          boolean tryLock()
                   throws IgniteException

      Acquires the lock only if it is free at the time of invocation.

      Acquires the lock if it is available and returns immediately with the value `true`. If the lock is not available then this method will return immediately with the value `false`.

      A typical usage idiom for this method would be:

           Lock lock = ...;
           if (lock.tryLock()) {
             try {
               // manipulate protected state
             } finally {
               lock.unlock();
             }
           } else {
             // perform alternative actions
           }

      This usage ensures that the lock is unlocked if it was acquired, and doesn't try to unlock if the lock was not acquired. If node is stopped, or any node failed while owning the lock in non-failoverSafe mode, then `IgniteException` is thrown.
      Specified by:
        `tryLock` in interface `Lock`
      Returns:
        `true` if the lock was acquired and `false` otherwise
      Throws:
        `IgniteException` - if node is stopped, or lock is already broken in non-failover safe mode

    - #### tryLock

          boolean tryLock​(long timeout,
                          TimeUnit unit)
                   throws IgniteInterruptedException,
                          IgniteException

      Acquires the lock if it is not held by another thread within the given waiting time and the current thread has not been interrupted.

      Acquires the lock if it is not held by another thread and returns immediately with the value `true`, setting the lock hold count to one.

      If the current thread already holds this lock then the hold count is incremented by one and the method returns `true`.

      If the lock is held by another thread then the current thread becomes disabled for thread scheduling purposes and lies dormant until one of five things happens:

      - The lock is acquired by the current thread; or
      - Some other thread interrupts the current thread; or
      - Lock is broken (any node failed while owning this lock), and lock is created in non-failoverSafe mode.
      - Local node is stopped.
      - The specified waiting time elapses

      If the lock is acquired then the value `true` is returned and the lock hold count is set to one.

      If the current thread:

      - has its interrupted status set on entry to this method; or
      - is interrupted while acquiring the lock; or
      then `IgniteInterruptedException` is thrown and the current thread's interrupted status is cleared.

      `IgniteException` is thrown in case:

      - the lock is broken before or during the attempt to acquire this lock; or
      - local node is stopped,

      If the specified waiting time elapses then the value `false` is returned. If the time is less than or equal to zero, the method will not wait at all.

      In this implementation, as this method is an explicit interruption point, preference is given to responding to the interrupt over normal or reentrant acquisition of the lock, and over reporting the elapse of the waiting time.

      Specified by:
        `tryLock` in interface `Lock`
      Parameters:
        `timeout` - the time to wait for the lock
        `unit` - the time unit of the timeout argument
      Returns:
        `true` if the lock was free and was acquired by the current thread, or the lock was already held by the current thread; and `false` if the waiting time elapsed before the lock could be acquired
      Throws:
        `IgniteInterruptedException` - if the current thread is interrupted
        `IgniteException` - if node is stopped, or lock is already broken in non-failover safe mode
        `NullPointerException` - if the time unit is null

    - #### unlock

          void unlock()
               throws IgniteInterruptedException

      Releases the lock. If lock is not owned by current thread, then an `IllegalMonitorStateException` is thrown. If lock is already broken prior to invocation of this method, and lock is created in non-failover safe mode, then `IgniteException` is thrown.
      Specified by:
        `unlock` in interface `Lock`
      Throws:
        `IllegalMonitorStateException` - if not owned by current thread
        `IgniteException` - if node is stopped, or lock is already broken in non-failover safe mode
        `IgniteInterruptedException`

    - #### getOrCreateCondition

          IgniteCondition getOrCreateCondition​(String name)
                                        throws IgniteException

      Returns a `Condition` instance for use with this `IgniteLock` instance.
      - If this lock is not held when any of the `Condition` waiting or signalling methods are called, then an `IllegalMonitorStateException` is thrown.
      - When the condition waiting methods are called the lock is released and, before they return, the lock is reacquired and the lock hold count restored to what it was when the method was called.
      - If a thread is interrupted while waiting then the wait will terminate, an `IgniteInterruptedException` will be thrown, and the thread's interrupted status will be cleared.
      - Waiting threads are signalled in FIFO order.
      Parameters:
        `name` - Name of the distributed condition object
      Returns:
        the Condition object
      Throws:
        `IgniteException` - if the lock is not initialized or already removed

    - #### newCondition

          Condition newCondition()

      This method is not supported in IgniteLock, Any invocation of this method will result in UnsupportedOperationException. Correct way to obtain Condition object is through method getOrCreateCondition(String)
      Specified by:
        `newCondition` in interface `Lock`

    - #### getHoldCount

          int getHoldCount()
                    throws IgniteException

      Queries the number of holds on this lock by the current thread.
      Returns:
        the number of holds on this lock by the current thread, or zero if this lock is not held by the current thread
      Throws:
        `IgniteException` - if the lock is not initialized or already removed

    - #### isHeldByCurrentThread

          boolean isHeldByCurrentThread()
                                 throws IgniteException

      Queries if this lock is held by the current thread.
      Returns:
        `true` if current thread holds this lock and `false` otherwise
      Throws:
        `IgniteException` - if the lock is not initialized or already removed

    - #### isLocked

          boolean isLocked()
                    throws IgniteException

      Queries if this lock is held by any thread on any node. This method is designed for use in monitoring of the system state, not for synchronization control.
      Returns:
        `true` if any thread on this or any other node holds this lock and `false` otherwise
      Throws:
        `IgniteException` - if the lock is not initialized or already removed

    - #### hasQueuedThreads

          boolean hasQueuedThreads()
                            throws IgniteException

      Queries whether any threads on this node are waiting to acquire this lock. Note that because cancellations may occur at any time, a `true` return does not guarantee that any other thread will ever acquire this lock. This method is designed primarily for use in monitoring of the system state.
      Returns:
        `true` if there may be other threads on this node waiting to acquire the lock
      Throws:
        `IgniteException` - if the lock is not initialized or already removed

    - #### hasQueuedThread

          boolean hasQueuedThread​(Thread thread)
                           throws IgniteException

      Queries whether the given thread is waiting to acquire this lock. Note that because cancellations may occur at any time, a `true` return does not guarantee that this thread will ever acquire this lock. This method is designed primarily for use in monitoring of the system state.
      Parameters:
        `thread` - the thread
      Returns:
        `true` if the given thread is queued waiting for this lock
      Throws:
        `NullPointerException` - if the thread is null
        `IgniteException` - if the lock is not initialized or already removed

    - #### hasWaiters

          boolean hasWaiters​(IgniteCondition condition)
                      throws IgniteException

      Queries whether any threads on this node are waiting on the given condition associated with this lock. Note that because timeouts and interrupts may occur at any time, a `true` return does not guarantee that a future `signal` will awaken any threads. This method is designed primarily for use in monitoring of the system state.
      Parameters:
        `condition` - the condition
      Returns:
        `true` if there are any waiting threads on this node
      Throws:
        `IllegalMonitorStateException` - if this lock is not held
        `IllegalArgumentException` - if the given condition is not associated with this lock
        `NullPointerException` - if the condition is null
        `IgniteException` - if the lock is not initialized or already removed

    - #### getWaitQueueLength

          int getWaitQueueLength​(IgniteCondition condition)
                          throws IgniteException

      Returns an estimate of the number of threads on this node that are waiting on the given condition associated with this lock. Note that because timeouts and interrupts may occur at any time, the estimate serves only as an upper bound on the actual number of waiters. This method is designed for use in monitoring of the system state, not for synchronization control.
      Parameters:
        `condition` - the condition
      Returns:
        the estimated number of waiting threads on this node
      Throws:
        `IllegalMonitorStateException` - if this lock is not held
        `IllegalArgumentException` - if the given condition is not associated with this lock
        `NullPointerException` - if the condition is null
        `IgniteException` - if the lock is not initialized or already removed

    - #### isFailoverSafe

          boolean isFailoverSafe()

      Returns `true` if this lock is safe to use after node failure. If not, IgniteInterruptedException is thrown on every other node after node failure.
      Returns:
        `true` if this reentrant lock has failoverSafe set true
      Throws:
        `IgniteException` - if the lock is not initialized or already removed

    - #### isFair

          boolean isFair()

      Returns `true` if this lock is fair. Fairness flag can only be set on lock creation.
      Returns:
        `true` if this reentrant lock has fairness flag set true.
      Throws:
        `IgniteException` - if the lock is not initialized or already removed

    - #### isBroken

          boolean isBroken()
                    throws IgniteException

      Returns true if any node that owned the locked failed before releasing the lock.
      Returns:
        true if any node failed while owning the lock since the lock on this node was initialized.
      Throws:
        `IgniteException` - if the lock is not initialized or already removed

    - #### removed

          boolean removed()

      Gets status of reentrant lock.
      Returns:
        `true` if reentrant lock was removed from cache, `false` in other case.

    - #### close

          void close()

      Removes reentrant lock.
      Specified by:
        `close` in interface `AutoCloseable`
      Specified by:
        `close` in interface `Closeable`
      Throws:
        `IgniteException` - If operation failed.