...ing logging 4.0

はてなブログに移行しました。D言語の話とかいろいろ。

銀行クラスをスレッドセーフに扱う

どこでどのような競合を起こしうるのか想像するのが難しい.
このようにスレッドセーフに使えるクラスを「スレッドコンパチブルである」という.

import std.stdio;
import core.thread;
import core.sync.mutex;

class Bank
{
	private int money_;
	
	void payin(int m)
	{
		money_ += m;
	}
	void payout(int m)
	{
		money_ -= m;
		if (money_ < 0)
		{
			// ここには来ない
			throw new Exception("pay out exception.");
		}
	}
	int money() @property
	{
		return money_;
	}
}

void main()
{
	auto bank = new Bank;
	auto tg = new ThreadGroup;
	bool isRunning = true;
	auto mutex = new Mutex;
	
	// 100ずつ出金する人
	tg.create = {
		while (isRunning)
		{
			try
			{
				synchronized (mutex)
				{
					if (bank.money >= 100) // 残金を確認して
					{
						foreach (_; 0..10000){} // 異常が起こりやすいように待つ
						// お金があるときだけ出金するはず?
						bank.payout(100);
					}
				}
			}
			catch (Exception e)
			{
				isRunning = false; // 両方のスレッドを終了する
				throw e;
			}
		}
	};
	
	// 100ずつ入金する人
	tg.create = {
		while (isRunning)
		{
			synchronized (mutex)
			{
				bank.payin(100);
			}
		}
	};
	
	// スレッドを回す
	tg.joinAll();
}