web-dev-qa-db-ja.com

ミューテックスは実際にどのように機能しますか?

ミューテックスの背後にある考え方は、一度に1つのスレッドのみがメモリのセクションにアクセスできるようにすることです。 1つのスレッドがミューテックスをロックすると、他のロックの試行は最初のスレッドがロック解除されるまでブロックされます。しかし、これはどのように実装されていますか?自分自身をロックするには、ミューテックスがロックされていることを示すビットをどこかに設定する必要があります。しかし、2番目のミューテックスが同時に読み取りを行っている場合はどうなりますか?さらに悪いことに、両方が同時にミューテックスをロックした場合はどうなりますか?ミューテックスは、それが防ぐことを意図しているのと同じ問題に屈するでしょう。

ミューテックスは実際にどのように機能しますか?

23
Joel

低レベルのアトミック操作。これらは基本的にハードウェアに実装されたミューテックスですが、アトミックに実行できる操作はごくわずかです。

次の同等の擬似コードを検討してください。

mutex global_mutex;
void InterlockedAdd(int& dest, int value) {
    scoped_lock lock(mutex);
    dest += value;
}
int InterlockedRead(int& src) {
    scoped_lock lock(mutex);
    return src;
}
void InterlockedWrite(int& dest, int value) {
    scoped_lock lock(mutex);
    dest = value;
}

これらの関数はCPUによる命令として実装され、さまざまな程度でスレッド間の一貫性を保証します。正確なセマンティクスは、問題のCPUによって異なります。 x86は逐次一貫性を提供します。これは、操作が、ある順序で順番に発行されたかのように動作することを意味します。これは明らかに少しブロックすることを含みます。

アトミック操作はミューテックスの観点から実装できる、またはその逆であると正確に推測できます。ただし、通常、アトミックopsはハードウェアによって提供され、その後、オペレーティングシステムによってミューテックスやその他の同期プリミティブがそれらの上に実装されます。これは、完全なミューテックスを必要とせず、「ロックレス」と呼ばれるものを操作できるアルゴリズムがいくつかあるためです。つまり、スレッド間の一貫性のためにアトミック操作を使用するだけです。

15
Puppy

過去に使用された単純な実装は、CPUレベルのアトミックな「ロックと交換」命令を使用することです。これは、特定の値を特定のメモリ位置の値とアトミックに交換する特別な命令です。

スレッドは、1の値をメモリ位置にスワップしようとすることで、このようなミューテックスを取得できます。値が0に戻った場合、スレッドはミューテックスを持っていると見なして続行します。それ以外の場合、返される値が1の場合、スレッドは一部のotherスレッドに現在ミューテックスがあることを認識します。その場合、再試行するまで待機します。

上記は、単純なシステムで発生する可能性のあることの非常に単純化された概要です。最近の実際のオペレーティングシステムははるかに複雑です。

13
Greg Hewgill

これはミューテックスが機能するために必要なものの簡単な概要です、それは私の完全な記事の短縮形です ミューテックスはどのように機能しますか?

  • ロック状態を表す整数がメモリにあり、値は1または0です。
  • ミューテックスには、その値をアトミックに変更して成功したかどうかを報告できるアトミックcompare_and_swap関数が必要です。これにより、スレッドは状態のチェックと変更の両方を同時に行うことができます。
  • OSは、ミューテックスがロックされた場合に待機する機能を提供する必要があります。 Linuxでは、低レベルの関数はfutexです。これにより、スレッドがキューに入れられ、メモリ内の整数も監視されます。
  • 関連する操作には、ロック前にメモリの変更が表示されないようにするためのデータフェンスも含まれ、ロック後に完全に使用可能になります。
6

必要なのはそれを原子的に行うことです。これは、アトミックな比較交換命令などのハードウェアによって、またはシステムコールを介してオペレーティングシステムによって提供できます。 OSドメインに入ると、1つのスレッドだけがミューテックスをロックしようとしていることを確認するのはかなり簡単です。

実際には、両方のアプローチが組み合わされています。たとえば、Linuxのfutexを参照してください。

3
DanielKO