クラスには次のロックメカニズムがあります。このプログラムを実行すると、1つのスレッドが継続的にロックを取得して再取得しますが、他のスレッドにロックを取得する機会を与えることはなく、飢餓につながります。スレッドがロックを放棄すると、別のスレッドがロックを取得するように、ロックメカニズムを再構築するにはどうすればよいですか?他のスレッドがロックを取得し、ロックされているスレッドの実行が停止するまで待つ必要がないようにしたいと思います。
private final ReentrantLock lock = new ReentrantLock();
private final Condition condition = lock.newCondition();
private final Map<Integer, Long> locksMap = new HashMap<Integer, Long>();
/** {@inheritDoc} */
@Override
public long lock(int recNo) throws RecordNotFoundException {
ValidationUtils.checkNegative(recNo);
lock.lock();
long id = Thread.currentThread().getId();
try {
while (locksMap.get(recNo) != null) {
try {
System.out.println("Thread " + id + " is waiting.");
condition.await();
}
catch (InterruptedException e) {
LOGGER.log(Level.SEVERE, e.getMessage());
return -1;
}
}
Long prevValue = locksMap.put(recNo, id);
if (prevValue != null) {
String msg = "Expected no value for " + recNo + " but was ";
msg += prevValue + ".";
throw new IllegalStateException(msg);
}
System.out.println("Thread " + id + " has the lock.");
}
finally {
lock.unlock();
}
return id;
}
/** {@inheritDoc} */
@Override
public void unlock(int recNo, long cookie) throws RecordNotFoundException, SecurityException {
ValidationUtils.checkNegative(recNo);
if (cookie < 0) {
throw new IllegalArgumentException("cookie is negative.");
}
lock.lock();
try {
if (locksMap.get(recNo) == cookie) {
locksMap.remove(recNo);
}
else {
String msg = "Wrong lock cookie. Expected " + locksMap.get(recNo);
msg += ", was " + cookie + ".";
throw new IllegalStateException(msg);
}
long id = Thread.currentThread().getId();
System.out.println("Thread " + id + " no longer has the lock.");
condition.signalAll();
}
finally {
lock.unlock();
}
}
/**
* Tests the locking mechanism in this class.
*
* @param args None.
*/
public static void main(String... args) {
ExecutorService threadPool = Executors.newFixedThreadPool(5);
final CountDownLatch latch = new CountDownLatch(5);
final Data data = new Data();
Runnable task = new Runnable() {
@Override
public void run() {
try {
for (int index = 0; index < 10; index++) {
long cookie = data.lock(1);
Thread.sleep(1000); // Do something.
data.unlock(1, cookie);
}
}
catch (SecurityException e) {
e.getStackTrace();
}
catch (RecordNotFoundException e) {
e.getStackTrace();
}
catch (InterruptedException e) {
e.getStackTrace();
}
finally {
latch.countDown();
}
}
};
for (int index = 0; index < 5; index++) {
threadPool.execute(task);
}
try {
latch.await();
}
catch (InterruptedException e) {
e.getStackTrace();
}
threadPool.shutdown();
}
これが出力です。スレッド9は、ループが終了した後にのみロックの取得を停止することに注意してください。
Thread 9 has the lock.
Thread 13 is waiting.
Thread 12 is waiting.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 9 no longer has the lock.
Thread 9 has the lock.
Thread 13 is waiting.
Thread 12 is waiting.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 9 no longer has the lock.
Thread 9 has the lock.
Thread 13 is waiting.
Thread 12 is waiting.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 9 no longer has the lock.
Thread 9 has the lock.
Thread 13 is waiting.
Thread 12 is waiting.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 9 no longer has the lock.
Thread 9 has the lock.
Thread 13 is waiting.
Thread 12 is waiting.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 9 no longer has the lock.
Thread 9 has the lock.
Thread 13 is waiting.
Thread 12 is waiting.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 9 no longer has the lock.
Thread 9 has the lock.
Thread 13 is waiting.
Thread 12 is waiting.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 9 no longer has the lock.
Thread 9 has the lock.
Thread 13 is waiting.
Thread 12 is waiting.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 9 no longer has the lock.
Thread 9 has the lock.
Thread 13 is waiting.
Thread 12 is waiting.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 9 no longer has the lock.
Thread 9 has the lock.
Thread 13 is waiting.
Thread 12 is waiting.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 9 no longer has the lock.
Thread 13 has the lock.
Thread 12 is waiting.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 13 no longer has the lock.
Thread 13 has the lock.
Thread 12 is waiting.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 13 no longer has the lock.
Thread 13 has the lock.
Thread 12 is waiting.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 13 no longer has the lock.
Thread 13 has the lock.
Thread 12 is waiting.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 13 no longer has the lock.
Thread 13 has the lock.
Thread 12 is waiting.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 13 no longer has the lock.
Thread 13 has the lock.
Thread 12 is waiting.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 13 no longer has the lock.
Thread 13 has the lock.
Thread 12 is waiting.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 13 no longer has the lock.
Thread 13 has the lock.
Thread 12 is waiting.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 13 no longer has the lock.
Thread 13 has the lock.
Thread 12 is waiting.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 13 no longer has the lock.
Thread 13 has the lock.
Thread 12 is waiting.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 13 no longer has the lock.
Thread 12 has the lock.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 12 no longer has the lock.
Thread 12 has the lock.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 12 no longer has the lock.
Thread 12 has the lock.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 12 no longer has the lock.
Thread 12 has the lock.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 12 no longer has the lock.
Thread 12 has the lock.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 12 no longer has the lock.
Thread 12 has the lock.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 12 no longer has the lock.
Thread 12 has the lock.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 12 no longer has the lock.
Thread 12 has the lock.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 12 no longer has the lock.
Thread 12 has the lock.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 12 no longer has the lock.
Thread 12 has the lock.
Thread 11 is waiting.
Thread 10 is waiting.
Thread 12 no longer has the lock.
Thread 11 has the lock.
Thread 10 is waiting.
Thread 11 no longer has the lock.
Thread 11 has the lock.
Thread 10 is waiting.
Thread 11 no longer has the lock.
Thread 11 has the lock.
Thread 10 is waiting.
Thread 11 no longer has the lock.
Thread 11 has the lock.
Thread 10 is waiting.
Thread 11 no longer has the lock.
Thread 11 has the lock.
Thread 10 is waiting.
Thread 11 no longer has the lock.
Thread 11 has the lock.
Thread 10 is waiting.
Thread 11 no longer has the lock.
Thread 11 has the lock.
Thread 10 is waiting.
Thread 11 no longer has the lock.
Thread 11 has the lock.
Thread 10 is waiting.
Thread 11 no longer has the lock.
Thread 11 has the lock.
Thread 10 is waiting.
Thread 11 no longer has the lock.
Thread 11 has the lock.
Thread 10 is waiting.
Thread 11 no longer has the lock.
Thread 10 has the lock.
Thread 10 no longer has the lock.
Thread 10 has the lock.
Thread 10 no longer has the lock.
Thread 10 has the lock.
Thread 10 no longer has the lock.
Thread 10 has the lock.
Thread 10 no longer has the lock.
Thread 10 has the lock.
Thread 10 no longer has the lock.
Thread 10 has the lock.
Thread 10 no longer has the lock.
Thread 10 has the lock.
Thread 10 no longer has the lock.
Thread 10 has the lock.
Thread 10 no longer has the lock.
Thread 10 has the lock.
Thread 10 no longer has the lock.
Thread 10 has the lock.
Thread 10 no longer has the lock.