Iは約APUE 3rd、11.6.1ミューテックスを読み、そこにロック約例であり、この章でミューテックスのロックを解除する:pthread_mutex_destroyを使ってLinuxでmutexを安全かつ正しく破壊するには?
foo_releでstruct foo {
int f_count;
pthread_mutex_t f_lock;
int f_id;
/* ... more stuff here ... */
};
struct foo *
foo_alloc(int id) /* allocate the object */
{
struct foo *fp;
if ((fp = malloc(sizeof(struct foo))) != NULL) {
fp->f_count = 1;
fp->f_id = id;
if (pthread_mutex_init(&fp->f_lock, NULL) != 0) {
free(fp);
return(NULL);
}
/* ... continue initialization ... */
}
return(fp);
}
void
foo_hold(struct foo *fp) /* add a reference to the object */
{
pthread_mutex_lock(&fp->f_lock);
fp->f_count++;
pthread_mutex_unlock(&fp->f_lock);
}
void
foo_rele(struct foo *fp) /* release a reference to the object */
{
pthread_mutex_lock(&fp->f_lock);
if (--fp->f_count == 0) { /* last reference */
pthread_mutex_unlock(&fp->f_lock);
pthread_mutex_destroy(&fp->f_lock);
free(fp);
} else {
pthread_mutex_unlock(&fp->f_lock);
}
}
、そこpthread_mutex_unlockのとpthread_mutex_destroyの間の競合状態があるので、Bスレッドは、のスレッドpthread_mutex_unlockとpthread_mutex_destroyの間でpthread_mutex_lockを呼び出すことができます。スレッドは未定義の動作を引き起こします(ロックされたミューテックスを破棄しようとすると、未定義の動作になります)。私は正しい?もし私が正しいのであれば、pthread_mutex_destroyを使って、それを正しく動作させる方法、またはLinuxでmutexを安全かつ正しく破壊する方法は?
あなたは、サンプルコードをチェックするために** ** 11.6.2デッドロック回避を参照してくださいでした、私は右だ、スレッドが唯一の直接ではない 'foo_hold'、' foo_find'を呼び出すことにより、オブジェクト参照を増やすことができると思います? – cong
はい、 'foo_find()'だけが 'foo_hold()'を呼び出します。 'foo_rele()'は、refcountを0に減らそうとすると、mutexを保持している間にハッシュテーブルからその項目を削除するので、他のスレッドは 'foo'オブジェクトへのポインタを再び取得できません。そのようなことが起こると、mutexはロック解除され、 'foo'オブジェクトのmutexは破壊され、' foo'オブジェクト自体は解放されます。 –
** foo_findのfoo_hold(fp);コードは、バージョン1のデュアルロック回避**の章のサンプルコードの2つのバージョンが、 'pthread_mutex_lock(&fp-> f_lock) ; fp-> f_count ++; pthread_mutex_unlock(&fp-> f_lock); ' と関数' foo_hold'を削除してください。 バージョン2では、 'foo_hold'関数を単に削除する必要があります。一方、それは役に立たず、危険ですが、ユーザーはインタフェースを誤用する可能性があります。 – cong