以下のミューテックスを。
なぜロック?
ロックは、クリティカル領域へのアクセスを表します。唯一のロックオブジェクトの動作に重要な地域を入力します。
ロックの本質とは何ですか?
ロックは、本質的にデータ構造(またはオブジェクト)は、オブジェクトがロックを記述するために必要不可欠な情報を保持します。このような現在のロックでスレッドが占有され、占有されているかどうかなど。ツール、ライブラリの一部のロックは、実際に変更を行うために、ロックオブジェクト情報です。
ロックオブジェクト情報を変更する操作=>の試みをロック、変更が成功した場合、プログラムがダウンし続け、それ以外の場合は、一時的にここに滞在します。(二つの方法で宿泊したことがあり、一方が他方のウェイクを待つために中断され、スピンを繰り返し試みです)
ロック解除操作=>ロックオブジェクト情報をリセットします。
このような何か(注:この例では、正確ではありません、後で話すます)
typedef struct __lock_t {
int flag; //锁的状态 0-空闲, 1-被占用
} lock_t;
void init(lock_t *mutex) { //初始化锁对象
mutex->flag = 0;
}
void lock(lock_t *mutex) {
while(mutex->flag == 1)
;// 自旋等待
mutex->flag = 1;
}
void unlock(lock_t *mutex) {
mutex->flag = 0;
}
ロック格納位置情報
一つは、オペレーティングシステムの仮想メモリを提供するので、プロセス内に保持されるので、ロックオブジェクトのメモリ空間は、唯一の現在のプロセスによってアクセスすることができます。そして、同じプロセスのスレッドがメモリリソースを共有することができます。したがって、このロックオブジェクトは、現在のプロセスのスレッドによってアクセスされることができます。
別のロック情報は、マシンの他のアプリケーションに格納されます。たとえば、マシンはRedisの外部アクセスを投入されていません。機械のような複数のアプリケーションがこのRedisのロックでのスケジュール情報によって管理することができます。
他のコンピュータアプリケーションはまた、ロックを分配されるロックにアクセスできるように別の他のマシンに格納された情報をロックすることで、(または機械がアクセス可能なRedisの外部になっています)。
ロック情報を変更するには
問題
先に述べたように、ロック情報の動作を変更するためのロック機能の前に問題がある、私たちは間違っていた最後に問題を見てください。私たちのコンピュータは1つのCPUのみを持っていると仮定し、この時間は、2つのスレッドがロックを取得しようとして始めたがあります。
この手順の結果は、スレッドBがロックを保持している場合、スレッドがロックを取得することができるということです。私たちは、このコードは正しさを満たしていない、「ミューテックス」が定義されて満たすことができません。だから、問題は、それがどこであるのですか?問題は、これら二つの動作が決定され、修正原子ではないことです。
上記の例のように、直前に実行されたスレッドAは、変更操作を行う、コンテキストスイッチが発生し、コード実行スレッドBの代わりにするのに十分な時間がないと判断されます。実際には、変更条件が発生した場合、スレッドはスイッチバック。
ハードウェアサポート
この問題のコードはOSのコンテキストスイッチが決定されるので、右の一般的なアプリケーションは干渉し、明確ではないアプリケーションが解決することができます。しかし、ハードウェアは、私たちは、この問題を解決することができますいくつかの指示プリミティブを提供します。これらのプリミティブは、追加フェッチと-、スワップを比較-と-、テスト・アンド・セットを持っている、というように、我々は、変更アトミック操作ロック情報を実装するために、これらのプリミティブに基づくことができます。例えば、我々はテスト・アンド・セットに基づいて達成することができます:
//test-and-set的C代码表示
int TestAndSet(int *ptr, int new) {
int old = *ptr; //抓取旧值
*ptr = new; //设置新值
return old; //返回旧值
}
typedef struct __lock_t {
int flag;
} lock_t;
void init (lock_t *lock) {
lock->flag = 0;
}
void lock(lock_t *lock) {
//如果为1,说明原来就有人在用
//如果不为1,说明原来没人在用,同时设置1,表明锁现在归我使用了
while (TestAndSet(&lock->flag, 1) == 1)
; //spin-wait (do noting)
}
void unlock (lock_t *lock) {
lock->flag = 0;
}
なぜ、これらの命令は、コンテキストスイッチによって中断されることはありませんか?
コンテキストスイッチ命令は、実際にハンドオーバを実行します。CPUは、テスト・アンド・セット命令は、コンテキストスイッチの必要性は、それが現在の命令を実行する前に完了するために、そうしても、CPUであり、そして、コンテキスト切り替え命令を実行する、命令を実行する実行します。