2005年2月17日

LiveLockを実装する。

DeadLockはよくJava入門書に書いてあるが、LiveLockはほとんど書かれていないので、擬似的に再現してみる。

デッドロックとは、スレッド1、スレッド2が存在した場合、相互にロックの取り合いを行い、処理が中断してしまうことである。ライブロックとは、スレッド1、スレッド2、スレッド3が存在した場合、スレッド1、スレッド2が交代してロックを取得することで全然スレッド3が処理を行わない状態を意味する。スレッド3自体は動作している、つまり生きている(Live)が餓死状態になっている。

org.oklab.thread.LiveLockクラスの実装

/*
 * 2005 Copyright satoshiokita All Right Reserved.
 */
package org.oklab.thread;

/**
 * Live Lock Sample Program.
 *
 * @version 0.01
 * @author satoshi okita
 *
 * 2005 Copyright satoshiokita All Right Reserved.
 */
public class LiveLock extends Thread {


	private String runningMessage = null;

	private ThreadState stateInstance = null;

	public LiveLock(String runningMessage) {
		super();
		this.runningMessage = runningMessage;

		/*
	     * instanciate default priority.
		 */
		stateInstance = new ThreadState();
	}

	public void setCustomPriority(int priority) {
		stateInstance.setPriority(priority);
	}

	public int getCustomPriority() {
		return (int) stateInstance.getPriority();
	}

	public void run() {
		while (true) {
			if (ThreadManager.exist(this) == true) {
				stateInstance.incrementEnergyCounter();
			}
			long resultCalc = stateInstance.getEnergyCounter() % 10000;
			if ((resultCalc % 10000) == 0 ) {
				System.out.print(this.getName() +" : ");
				System.out.println(
				stateInstance.getEnergyCounter());
			}
		}
	}

	class ThreadState {
		private long energyCounter;
		private long priority;

   		public ThreadState() {
   			energyCounter = 100L;
   			priority = 1L;
   		}

   		public ThreadState(long priority) {
   			this.priority = priority;
   		}

   		public ThreadState(long energyCounter, long priority) {
   			this.energyCounter = energyCounter;
   			this.priority = priority;
   		}

   		public void setEnergyCounter(long energyCounter) {
   			this.energyCounter = energyCounter;
   		}
   		
   		public long getEnergyCounter() {
   			return energyCounter;
   		}

   		public void incrementEnergyCounter() {
   			energyCounter++;
   		}

   		public void setPriority(long priority) {
   			this.priority = priority;
   		}
   
   		public long getPriority() {
   			return priority;
   		}
	}
}

org.oklab.thread.ThreadManagerクラスの実装

/*
* 2005 Copyright satoshiokita All Right Reserved.
*/

package org.oklab.thread;

import java.util.Set;
import java.util.HashSet;

/**
 * The Thread Manager automanically administrate LiveLock Thread.
 *
 * @version 0.01
 * @author satoshi okita
 *
 * 2005 Copyright satoshiokita All Right Reserved.
 */
public class ThreadManager {

	private static Set threadPool = new HashSet();

	private static boolean setThread(Runnable implementThread)
			throws Exception {
		boolean checkExist = threadPool.add(implementThread);

		if ( checkExist == false ) {
			throw new Exception("pool has same thread.");
		}

		return checkExist;
	}

	public static boolean exist(Object object) {
		return threadPool.contains(object);
	}

	/**
	 * Louncher.
	 * @param String []
	 */
	public static void main(String [] args) {
		LiveLock thread1 = new LiveLock("1");
		LiveLock thread2 = new LiveLock("2");
		LiveLock thread3 = new LiveLock("3");
		
		try {
			ThreadManager.setThread(thread1);
			ThreadManager.setThread(thread2);
			// ThreadManager.setThread(thread3);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		System.out.println(ThreadManager.exist(thread1));
		thread1.setCustomPriority(Thread.MAX_PRIORITY);
		thread1.start();
		System.out.println("debug:th1:" + thread1.getPriority());
		thread2.setCustomPriority(Thread.MAX_PRIORITY);
		thread2.start();
		System.out.println("debug:th2:" + thread2.getPriority());
		thread3.setCustomPriority(Thread.MIN_PRIORITY);
		thread3.start();
		System.out.println("debug:th3:" + thread3.getPriority());
	}
}

このサンプルでは、LiveLockのインスタンスthread3が、ロックを取得できず飢餓状態に陥る。