@prefix schema: <https://schema.org/> .
@prefix skos: <http://www.w3.org/2004/02/skos/core#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix ks: <https://comcomponent.com/vocab/> .

<https://comcomponent.com/blog/windows-condition-variable-spurious-wakeup/#article>
    schema:about <https://comcomponent.com/knowledge/spurious-wakeup/>, <https://comcomponent.com/knowledge/predicate-while-loop/> ;
    schema:mentions <https://comcomponent.com/knowledge/win32-condition-variable/>, <https://comcomponent.com/knowledge/std-condition-variable/>, <https://comcomponent.com/knowledge/stolen-wakeup/>, <https://comcomponent.com/knowledge/predicate-wait-overload/>, <https://comcomponent.com/knowledge/lost-wakeup/>, <https://comcomponent.com/knowledge/monitor-wait-pulse/>, <https://comcomponent.com/knowledge/wait-on-address/>, <https://comcomponent.com/knowledge/pulseevent/>, <https://comcomponent.com/knowledge/kernel-apc/>, <https://comcomponent.com/knowledge/critical-section/>, <https://comcomponent.com/knowledge/srw-lock/>, <https://comcomponent.com/knowledge/race-condition/>, <https://comcomponent.com/knowledge/deadlock/> .

<https://comcomponent.com/knowledge/spurious-wakeup/> a skos:Concept ;
    skos:prefLabel "スプリアスウェイクアップ"@ja ;
    skos:definition "通知がないのに条件変数の待機から目覚めてしまう現象。"@ja .

<https://comcomponent.com/knowledge/predicate-while-loop/> a skos:Concept ;
    skos:prefLabel "述語のwhileループ再確認"@ja ;
    skos:definition "待機操作から戻るたびに待っていた条件そのものを確認し、成立していなければもう一度待つ書き方。"@ja ;
    ks:prevents <https://comcomponent.com/knowledge/race-condition/> .

<https://comcomponent.com/knowledge/win32-condition-variable/> a skos:Concept ;
    skos:prefLabel "Win32の条件変数"@ja ;
    skos:definition "InitializeConditionVariableで作り、SleepConditionVariableCS／SRWで待ち、WakeConditionVariableで起こすWin32の待ち合わせ機構。"@ja ;
    ks:mayCause <https://comcomponent.com/knowledge/spurious-wakeup/> ;
    ks:mayCause <https://comcomponent.com/knowledge/stolen-wakeup/> ;
    ks:uses <https://comcomponent.com/knowledge/critical-section/> ;
    ks:uses <https://comcomponent.com/knowledge/srw-lock/> ;
    ks:prevents <https://comcomponent.com/knowledge/lost-wakeup/> ;
    ks:succeeds <https://comcomponent.com/knowledge/pulseevent/> .

<https://comcomponent.com/knowledge/stolen-wakeup/> a skos:Concept ;
    skos:prefLabel "横取り(stolen wakeup)"@ja ;
    skos:definition "起こされたスレッドがロックを再取得して戻るまでの間に、別のスレッドが先に条件を消費してしまうこと。"@ja .

<https://comcomponent.com/knowledge/critical-section/> a skos:Concept ;
    skos:prefLabel "CRITICAL_SECTION"@ja ;
    skos:definition "スピンしてからカーネル待機に落ちる、プロセス内専用のWin32ロック。同一スレッドの再帰取得ができる。"@ja .

<https://comcomponent.com/knowledge/srw-lock/> a skos:Concept ;
    skos:prefLabel "SRWロック(Slim Reader/Writer Lock)"@ja ;
    skos:definition "Win32が提供する軽量な読み書きロック。再帰取得はできない。"@ja ;
    skos:altLabel "SRWLOCK" .

<https://comcomponent.com/knowledge/race-condition/> a skos:Concept ;
    skos:prefLabel "競合状態(race condition)"@ja ;
    skos:definition "複数のスレッドがどの順序で特定のコードに到達するかによって結果が変わってしまう不具合。"@ja ;
    skos:altLabel "レースコンディション"@ja .

<https://comcomponent.com/knowledge/predicate-wait-overload/> a skos:Concept ;
    skos:prefLabel "述語付きwait(lock, pred)"@ja ;
    skos:definition "実質的に while (!pred()) wait(lock); を実行する、C++の条件変数の待機オーバーロード。"@ja ;
    ks:implements <https://comcomponent.com/knowledge/predicate-while-loop/> .

<https://comcomponent.com/knowledge/std-condition-variable/> a skos:Concept ;
    skos:prefLabel "std::condition_variable"@ja ;
    skos:definition "ミューテックスと組み合わせて、条件が満たされるまでスレッドを待たせるC++の同期プリミティブ。"@ja ;
    ks:uses <https://comcomponent.com/knowledge/predicate-wait-overload/> ;
    ks:mayCause <https://comcomponent.com/knowledge/spurious-wakeup/> .

<https://comcomponent.com/knowledge/wait-on-address/> a skos:Concept ;
    skos:prefLabel "WaitOnAddress"@ja ;
    skos:definition "指定アドレスの値が変わるのを待つ、条件変数より原始的な待機API。シグナル時に戻ることは保証されるが、それ以外の理由で戻ることも許されている。"@ja ;
    ks:mayCause <https://comcomponent.com/knowledge/spurious-wakeup/> .

<https://comcomponent.com/knowledge/monitor-wait-pulse/> a skos:Concept ;
    skos:prefLabel "Monitor.Wait / Pulse / PulseAll"@ja ;
    skos:definition "ロックを解放して待機キューに入り、Pulse系で起こされてレディキューへ移り、ロックを取り直してから戻る.NETの待ち合わせ。"@ja ;
    ks:mayCause <https://comcomponent.com/knowledge/stolen-wakeup/> ;
    ks:requires <https://comcomponent.com/knowledge/predicate-while-loop/> .

<https://comcomponent.com/knowledge/lost-wakeup/> a skos:Concept ;
    skos:prefLabel "起こし損ね(lost wakeup)"@ja ;
    skos:definition "待機側がロックの外で条件を見てから待機に入るまでの隙間に通知が通り過ぎ、二度と来ない通知を待ち続けること。"@ja ;
    ks:mayCause <https://comcomponent.com/knowledge/deadlock/> .

<https://comcomponent.com/knowledge/deadlock/> a skos:Concept ;
    skos:prefLabel "デッドロック(deadlock)"@ja ;
    skos:definition "複数のタスクが互いの完了やリソース解放を待ち続け、永遠に進行しなくなる状態である。"@ja ;
    skos:altLabel "Deadlock" .

<https://comcomponent.com/knowledge/pulseevent/> a skos:Concept ;
    skos:prefLabel "PulseEvent"@ja ;
    skos:definition "手動リセットイベントで「今待っている全員を起こしてすぐ非シグナルに戻す」API。マイクロソフト自身が信頼できないため使うべきでないとしている。"@ja ;
    ks:mayCause <https://comcomponent.com/knowledge/lost-wakeup/> .

<https://comcomponent.com/knowledge/kernel-apc/> a skos:Concept ;
    skos:prefLabel "カーネルモードAPC"@ja ;
    skos:definition "プリエンプティブに実行され、待機APIを戻すことなくシステムが内部的に待機を中断・再開させる仕組み。アプリ側から制御できない。"@ja .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/win32-condition-variable/> ;
    rdf:predicate ks:mayCause ;
    rdf:object <https://comcomponent.com/knowledge/spurious-wakeup/> ;
    schema:description "条件変数はロックの解放と待機への移行を不可分に行うユーザーモードオブジェクトだが、明示的な起床と結びつかない目覚めの対象となる。"@ja ;
    ks:evidence <https://learn.microsoft.com/windows/win32/sync/condition-variables> ;
    ks:verifiedAt "2026-08-22" ;
    ks:certainty "established" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/win32-condition-variable/> ;
    rdf:predicate ks:mayCause ;
    rdf:object <https://comcomponent.com/knowledge/stolen-wakeup/> ;
    schema:description "通知側がWakeConditionVariableを呼んでから、起こされたスレッドがロックを再取得してwaitから戻るまでには必ず時間差がある。その間にロックを取れる第三のスレッドがいれば、条件を先に消費できてしまう。"@ja ;
    ks:evidence <https://learn.microsoft.com/windows/win32/sync/condition-variables> ;
    ks:verifiedAt "2026-08-22" ;
    ks:certainty "established" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/win32-condition-variable/> ;
    rdf:predicate ks:uses ;
    rdf:object <https://comcomponent.com/knowledge/critical-section/> ;
    schema:description "SleepConditionVariableCSは、指定したクリティカルセクションの解放と条件変数での待機を不可分に行い、目覚めるときはロックを再取得してから戻る。"@ja ;
    ks:evidence <https://learn.microsoft.com/windows/win32/api/synchapi/nf-synchapi-sleepconditionvariablecs> ;
    ks:verifiedAt "2026-08-22" ;
    ks:certainty "established" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/win32-condition-variable/> ;
    rdf:predicate ks:uses ;
    rdf:object <https://comcomponent.com/knowledge/srw-lock/> ;
    schema:description "SleepConditionVariableSRWを使えば、クリティカルセクションの代わりにSRWロックと組み合わせて同じ待ち合わせができる。どちらか一方のロックと組で使う。"@ja ;
    ks:evidence <https://learn.microsoft.com/windows/win32/sync/condition-variables> ;
    ks:verifiedAt "2026-08-22" ;
    ks:certainty "established" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/predicate-while-loop/> ;
    rdf:predicate ks:prevents ;
    rdf:object <https://comcomponent.com/knowledge/race-condition/> ;
    schema:description "スプリアスウェイクアップも横取りも発生自体は消せないが、waitから戻るたびに待っていた条件そのものを確認し、成立していなければもう一度眠ることで、条件不成立のまま処理が進むことを防げる。3つのどの経路で戻ってきたかを呼び出し側は区別できないため、これが唯一の戦略になる。公式の生産者・消費者キューの使用例も待機をwhileループで書いている。"@ja ;
    ks:evidence <https://learn.microsoft.com/windows/win32/sync/condition-variables>, <https://learn.microsoft.com/windows/win32/sync/using-condition-variables> ;
    ks:verifiedAt "2026-08-22" ;
    ks:certainty "established" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/predicate-wait-overload/> ;
    rdf:predicate ks:implements ;
    rdf:object <https://comcomponent.com/knowledge/predicate-while-loop/> ;
    schema:description "述語なしのwaitはnotify_one / notify_allでシグナルされるまでブロックするがスプリアスに目覚めることもあり、述語付きのwait(lock, pred)は実質的に while (!pred()) wait(lock); を実行する。"@ja ;
    ks:evidence <https://learn.microsoft.com/cpp/standard-library/condition-variable-class>, <https://en.cppreference.com/w/cpp/thread/condition_variable/wait> ;
    ks:verifiedAt "2026-08-22" ;
    ks:certainty "established" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/std-condition-variable/> ;
    rdf:predicate ks:uses ;
    rdf:object <https://comcomponent.com/knowledge/predicate-wait-overload/> ;
    schema:description "C++で推奨される述語付きwaitは、whileで囲む規律をライブラリが肩代わりする形にほかならない。新規コードの既定はこちらになる。"@ja ;
    ks:evidence <https://learn.microsoft.com/cpp/standard-library/condition-variable-class> ;
    ks:verifiedAt "2026-08-22" ;
    ks:certainty "established" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/std-condition-variable/> ;
    rdf:predicate ks:mayCause ;
    rdf:object <https://comcomponent.com/knowledge/spurious-wakeup/> ;
    schema:description "スプリアスウェイクアップはPOSIXもWindowsもC++規格もそろって許した仕様で、ちょうど1つのスレッドだけを確実に起こす通知を厳密に実装すると、特にマルチプロセッサ環境で条件変数のすべての操作に余分な同期コストがかかるためである。ループの強制はコードを自己文書化し、より堅牢にするとも述べられている。"@ja ;
    ks:evidence <https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_timedwait.html>, <https://en.cppreference.com/w/cpp/thread/condition_variable/wait> ;
    ks:verifiedAt "2026-08-22" ;
    ks:certainty "established" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/wait-on-address/> ;
    rdf:predicate ks:mayCause ;
    rdf:object <https://comcomponent.com/knowledge/spurious-wakeup/> ;
    schema:description "アドレスの値が変わるのを待つ最下層に近いAPIですら、シグナル時に戻ることは保証されるがそれ以外の理由で戻ることも許されている。低メモリ状態や過去のwakeの放棄が早期に目覚める例として挙げられ、使用例そのものが値を比較し直すwhileループの形をしている。"@ja ;
    ks:evidence <https://learn.microsoft.com/windows/win32/api/synchapi/nf-synchapi-waitonaddress> ;
    ks:verifiedAt "2026-08-22" ;
    ks:certainty "established" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/monitor-wait-pulse/> ;
    rdf:predicate ks:mayCause ;
    rdf:object <https://comcomponent.com/knowledge/stolen-wakeup/> ;
    schema:description "PulseAllは待機キューのスレッドをレディキューに移し、ロックが解放されるとレディキューのスレッドがロックを取り直せた順にWaitから戻る。取り直すまでの間に別のスレッドが条件を消費できる点はWin32と同じで、起こされたスレッドは待機に入った原因の条件を評価し直し、必要ならもう一度Waitを呼ぶ使い方が想定されている。"@ja ;
    ks:evidence <https://learn.microsoft.com/dotnet/api/system.threading.monitor.wait>, <https://learn.microsoft.com/dotnet/api/system.threading.monitor.pulseall> ;
    ks:verifiedAt "2026-08-22" ;
    ks:certainty "established" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/monitor-wait-pulse/> ;
    rdf:predicate ks:requires ;
    rdf:object <https://comcomponent.com/knowledge/predicate-while-loop/> ;
    schema:description ".NETでも規律は変わらず、whileで条件を確認してからWaitに戻る。"@ja ;
    ks:evidence <https://learn.microsoft.com/dotnet/api/system.threading.monitor.wait> ;
    ks:verifiedAt "2026-08-22" ;
    ks:certainty "established" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/lost-wakeup/> ;
    rdf:predicate ks:mayCause ;
    rdf:object <https://comcomponent.com/knowledge/deadlock/> ;
    schema:description "待機側がロックの外で条件を見て待機に入ろうとした隙間に通知側が状態を更新して通知を送ると、通知は待機者のいない条件変数へ向けて発射されて消え、待機側は二度と来ない通知を待ち続ける。"@ja ;
    ks:evidence <https://learn.microsoft.com/windows/win32/sync/condition-variables> ;
    ks:verifiedAt "2026-08-22" ;
    ks:certainty "established" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/win32-condition-variable/> ;
    rdf:predicate ks:prevents ;
    rdf:object <https://comcomponent.com/knowledge/lost-wakeup/> ;
    schema:description "条件変数の待機APIがロックの解放と眠りへの移行を不可分に行うよう設計されているのは、まさにこの隙間を閉じるためで、ロックの規律を守っている限り起きない。"@ja ;
    ks:evidence <https://learn.microsoft.com/windows/win32/sync/condition-variables> ;
    ks:verifiedAt "2026-08-22" ;
    ks:certainty "established" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/spurious-wakeup/> ;
    rdf:predicate ks:mayCause ;
    rdf:object <https://comcomponent.com/knowledge/race-condition/> ;
    schema:description "ifで1回だけ確認して待機に入るコードは、スプリアスウェイクアップか横取りが起きた瞬間に条件不成立のまま処理が進み、空のキューからの取り出しや未初期化データの参照といった、たまにしか出ないクラッシュ・データ破損になる。"@ja ;
    ks:evidence <https://learn.microsoft.com/windows/win32/sync/condition-variables> ;
    ks:verifiedAt "2026-08-22" ;
    ks:certainty "context-dependent" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/pulseevent/> ;
    rdf:predicate ks:mayCause ;
    rdf:object <https://comcomponent.com/knowledge/lost-wakeup/> ;
    schema:description "待機中のスレッドがカーネルモードAPCで一時的に待機状態から外され、APC完了後に戻ることがある。その一瞬の間にPulseEventが呼ばれると、そのスレッドは「呼ばれた瞬間に待機していた者」に含まれず起こされない。whileループでも救えない、通知そのものが失われる問題である。"@ja ;
    ks:evidence <https://learn.microsoft.com/windows/win32/api/winbase/nf-winbase-pulseevent> ;
    ks:verifiedAt "2026-08-22" ;
    ks:certainty "established" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/kernel-apc/> ;
    rdf:predicate ks:mayCause ;
    rdf:object <https://comcomponent.com/knowledge/lost-wakeup/> ;
    schema:description "カーネルAPCはプリエンプティブに実行され、待機APIを戻すことなくシステムが内部的に待機を中断する。その一瞬の間にPulseEventが呼ばれると、そのスレッドは「呼ばれた瞬間に待機していた者」に含まれず起こされない。カーネルAPCはOSが内部的に使うもので、アプリ側から制御できない。"@ja ;
    ks:evidence <https://learn.microsoft.com/windows-hardware/drivers/kernel/waits-and-apcs>, <https://learn.microsoft.com/windows/win32/api/winbase/nf-winbase-pulseevent> ;
    ks:verifiedAt "2026-08-22" ;
    ks:certainty "context-dependent" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/win32-condition-variable/> ;
    rdf:predicate ks:succeeds ;
    rdf:object <https://comcomponent.com/knowledge/pulseevent/> ;
    schema:description "PulseEventは信頼できないため使うべきではなく、主に後方互換のために存在し、代わりに条件変数を使うべきだと明言されている。静的解析の警告C28648にもなっている。"@ja ;
    ks:evidence <https://learn.microsoft.com/windows/win32/api/winbase/nf-winbase-pulseevent>, <https://learn.microsoft.com/windows-hardware/drivers/devtest/28648-pulseevent-is-an-unreliable-function> ;
    ks:verifiedAt "2026-08-22" ;
    ks:certainty "established" .
