原因の分からない不具合に悩まされる話(解決)

2月も終わり、そろそろ暖かくなってくる頃合いです。
今度は花粉に悩まされる季節到来ですね…。

最近は常時マスクをしているので、くしゃみ鼻水は軽減されそうですが、
目が痒くなるのは如何ともしがたいところです。


さて表題の件ですが、先月問題となっていた項目について
原因が判明したため書いてみたいと思います。

結論から書きますと、原因は
「処理がスレッドセーフになっていなかったため」
でした。

javaのqueueクラスはスレッドセーフでは無いため、複数のスレッドからアクセスされる環境だと
予期しない動作となってしまうことがあるわけですが、そこの対策が行われていませんでした。

一応、今回問題が起こった場合の具体的な動作についても記載しておきます。

queueにaddする処理とpollする処理がまずいタイミングで同時実行されてしまうと、
queueのsize()がおかしな値となってしまい、size()で取得された値が1以上なのに、pollした結果がnull、
といった結果になっていました。

public class StatusMonitoringThread extends Thread {
	private Queue<QueInfo> queue; // ⇐スレッドセーフではない
	
	public StatusMonitoringThread() {
		queue = new ArrayDeque<QueInfo>(); // ⇐スレッドセーフではない
		// queueをstaticなクラスに登録し、外部からadd可能にしておく
					:
					:
	}
	
	public void run() {
		QueInfo deQue;
		while(true) {
			// キューチェック
			if( queue.size() > 0 ) { // ⇐size()が1以上なのにpollの結果がnullといった事態が発生
				deQue = queue.poll();
				// 取得情報を元に、各種処理を実施
					:
			}
			
			try {
				Thread.sleep(1);
			}
			catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}

対策としては、queueクラスをConcurrentLinkedQueueクラスに置き換えることで
問題は解決されました。

複数のスレッドからアクセスされる変数については細心の注意を払わないといけませんね。

以上