/** {@inheritDoc} */
  @Override
  protected SoftLock lock(Object key) throws CacheException {
    try {
      TxContext ctx = txCtx.get();

      if (ctx == null) txCtx.set(ctx = new TxContext());

      lockKey(key);

      ctx.locked(key);

      return null;
    } catch (GridException e) {
      rollbackCurrentTx();

      throw new CacheException(e);
    }
  }
  /**
   * @param ctx Transaction context.
   * @param key Key.
   * @throws GridException If failed.
   */
  private void unlock(TxContext ctx, Object key) throws GridException {
    if (ctx.unlocked(key)) { // Finish transaction if last key is unlocked.
      txCtx.remove();

      GridCacheTx tx = cache.tx();

      assert tx != null;

      try {
        tx.commit();
      } finally {
        tx.close();
      }

      assert cache.tx() == null;
    }
  }