現在、C# でプロジェクトに取り組んでいます。単一のロックを使用して状態変数へのアクセスを同期しています。この状態変数は、一定期間設定されるようにトリガーされ、その後、その値をリセットする必要があります。私の現在のコードは次のとおりです。
using System.Threading;
class Test
{
object syncObj = new object();
bool state = false;
Timer stateTimer;
Test()
{
stateTimer = new Timer(ResetState, this, Timeout.Infinite, Timeout.Infinite);
}
void SetState()
{
lock(syncObj)
{
state = true;
stateTimer.Change(1000, Timeout.Infinite);
}
}
static void ResetState(object o)
{
Test t = o as Test;
lock(t.syncObj)
{
t.state = false;
}
}
}
Timer によって ResetState が呼び出される前に SetState を再度呼び出すことが有効であること (つまり、状態が true である期間を延長できること) を考えると、単一のロックでは不十分な状況が想像できます。私が考えている具体的なケースはこれです
- SetState と ResetState の両方が、それぞれメイン スレッドとタイマー スレッドで同時に入力されます。
- SetState は最初にロックを取得し、状態を正しく true に設定し、タイマーをトリガーして再度開始します。
- その後、ResetState は誤って状態を false に設定します。これは、予想される期間、状態が true ではないことを意味します。
私はしばらくの間、これについて頭を悩ませてきました。それを解決できるようになった最も近い方法は、2 つのロックを使用することでしたが、最終的には、これが他の問題を引き起こしていることがわかりました (少なくとも、私が行った方法では)。
この問題を解決する既知の方法はありますか (また、同期に関する知識を更新するために何かを読む必要があります)。
更新: このインスタンスでは、タイマーの現在の状態を照会できないことを忘れていました。可能であれば、ResetState の残り時間をチェックして、タイマーが本当に停止しているかどうかを判断することを想像できます。