All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.liferay.portal.kernel.concurrent.CompeteLatch Maven / Gradle / Ivy

Go to download

Contains interfaces for the portal services. Interfaces are only loaded by the global class loader and are shared by all plugins.

There is a newer version: 7.0.0-nightly
Show newest version
/**
 * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or (at your option)
 * any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 */

package com.liferay.portal.kernel.concurrent;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;

/**
 * A synchronizer based on the JDK's AQS framework to simulate a single winner
 * competition. This synchronizer supports cyclical competition. In this
 * situation, loser threads should try again. The single winner thread will lock
 * the latch while other threads will block on the latch by calling
 * await. After the winner thread finishes its job, it should call
 * done which will open the latch. All blocking loser threads can
 * pass the latch at the same time.
 *
 * 

* See LPS-3744 for a sample use case. *

* * @author Shuyang Zhou */ public class CompeteLatch { /** * This method should only be called by a loser thread. If the latch is * locked, that means the winner is executing its job and all loser threads * that call this method will be blocked. If the latch is not locked, that * means the winner has finished its job and all the loser threads calling * this method will return immediately. If the winner thread calls this * method before his job completed, then all threads will deadlock. * * @throws InterruptedException if the current thread is interrupted */ public void await() throws InterruptedException { _sync.acquireSharedInterruptibly(1); } /** * This method should only be called by a loser thread. If the latch is * locked, that means the winner is executing its job and all loser threads * that call this method will be blocked for the given waiting time. If the * latch is not locked, that means the winner has finished its job and all * the loser threads calling this method will return immediately. If the * winner thread calls this method before his job completed, then all * threads will deadlock. * * @param timeout the timeout value * @param timeUnit the time unit * @return true if the latch was open, false if * the waiting time elapsed before the latch be opened. * @throws InterruptedException if the current thread is interrupted */ public boolean await(long timeout, TimeUnit timeUnit) throws InterruptedException { return _sync.tryAcquireSharedNanos(1, timeUnit.toNanos(timeout)); } /** * Tells the current thread to join the competition. Return immediately * whether or not the current thread is the winner thread or a loser thread. * No matter how many threads join this competition, only one thread can be * the winner thread. * * @return true if the current thread is the winner thread */ public boolean compete() { return _sync._tryInitAcquireShared(); } /** * This method should only be called by the winner thread. The winner thread * calls this method to indicate that it has finished its job and unlocks * the latch to allow all loser threads return from the await * method. If a loser thread does call this method when a winner thread has * locked the latch, the latch will break and the winner thread may be put * into a non thread safe state. You should never have to do this except to * get out of a deadlock. If no one threads have locked the latch, then * calling this method has no effect. This method will return immediately. * * @return true if this call opens the latch, * false if the latch is already open */ public boolean done() { return _sync.releaseShared(1); } /** * Returns true if the latch is locked. This method should not * be used to test the latch before joining a competition because it is not * thread safe. The only purpose for this method is to give external systems * a way to monitor the latch which is usually be used for deadlock * detection. * * @return true if the latch is locked; false * otherwise */ public boolean isLocked() { return _sync._isLocked(); } private Sync _sync = new Sync(); private class Sync extends AbstractQueuedSynchronizer { @Override protected int tryAcquireShared(int arg) { if (getState() == 0) { return 1; } else { return -1; } } @Override protected boolean tryReleaseShared(int arg) { if (compareAndSetState(1, 0)) { return true; } else { return false; } } private boolean _isLocked() { if (getState() == 1) { return true; } else { return false; } } private boolean _tryInitAcquireShared() { if (compareAndSetState(0, 1)) { return true; } else { return false; } } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy