2

スレッドセーフにしたいObjective-Cクラスを書いています。これを行うために、私は pthreads と a を使用していますpthread_rwlock(使用はやり@synchronized過ぎです。pthreads についてもう少し学びたいと思います)。メソッドで指定されたオブジェクトでロックが開始され、initで破棄されdeallocます。ロックを操作するには 3 つの方法があります。readLockwriteLockunlock。これら 3 つのメソッドは、関連する pthread 関数を呼び出すだけで、現在のところ他には何もありません。

以下に 2 つのオブジェクト メソッドを示します。どちらも writeLock を必要とします。

-(void)addValue:(const void *)buffer
{
    [self writeLock];

    NSUInteger lastIndex = self.lastIndex;
    [self setValue:buffer atIndex:(lastIndex == NSNotFound) ? 0 : lastIndex+1];

    [self unlock];
}


-(void)setValue:(const void *)buffer atIndex:(NSUInteger)index
{
    [self writeLock];
    //do work here
    [self unlock];
}

呼び出しsetAddValue:は最初に書き込みロックを取得し、次に呼び出しsetValue:atIndex:も書き込みロックを取得しようとします。ドキュメントには、これが発生した場合の動作は未定義であると記載されています。したがって、ロックを取得しようとする前に、スレッドがロックされているかどうかを確認するにはどうすればよいでしょうか?

(クリティカル セクションが別のロック要求をトリガーする呼び出しを行わないようにすることはできますが、それはコードの繰り返しを意味し、コードを DRY に保ちたいと考えています)。

4

3 に答える 3

2

使用しているロックの種類が完全にはわかりません。あなたは pthreads と読み取り/書き込みロックを使用していることを示しているので、pthread_rwlock を使用していると結論付けています。

pthread_rwlock_trywrlockそれが本当なら、ロックで使用できるはずです。マニュアルページから、

成功した場合、pthread_rwlock_wrlock() および pthread_rwlock_trywrlock() 関数はゼロを返します。それ以外の場合は、エラーを示すエラー番号が返されます。

そして、エラーの1つは次のとおりです。

[EDEADLK] 呼び出しスレッドは既に読み取り/書き込みロック (読み取りまたは書き込み用) を所有しています。

したがって、呼び出すことができるはずでありpthread_rwlock_trywrlock()、成功するかEBUSY、別のスレッドがロックを持っている場合は返されるEDEADLKか、現在のスレッドがロックを持っている場合は取得すると思います。

于 2011-04-23T18:55:15.187 に答える
0

まず、1 つの操作のみを含むクリティカル セクションは役に立ちません。ポイントは、さまざまなものを互いに同期させることです。(整数を事実上アトミックにしますが、それはおそらく完全な意図ではありません。)

次に、後者のクリティカル セクション内に書き込みロックがあることは既にわかっているため、存在するかどうかを確認する必要はありません。書き込み中に読み取りロックを試行しないでください。

解決策はおそらくreadLockandwriteLockの呼び出しを呼び出し関数に移動することですが、それ以上のことを知らなければ何とも言えません。

(これにより、操作の合計数が減るため、ロックのパフォーマンス コストも削減される可能性があります。ロックしてからすぐにロック解除する必要がないためです。おそらく、pthreads レベルで直接作業する必要はありません。)

于 2011-04-23T18:37:57.273 に答える
0

移植可能なプログラムは、実装に依存して、既に書き込みロックを保持していることを呼び出し元に伝えることはできません。代わりに、rwlocks を再帰的な書き込みロックでラップするには、次のようにする必要があります。

int wrlock_wrap(pthread_rwlock_t *l, int *cnt)
{
    int r = *cnt ? 0 : pthread_rwlock_wrlocK(l);
    if (!r) ++*cnt;
    return r;
}

int wrunlock_wrap(pthread_rwlock_t *l, int *cnt)
{
    --*cnt;
    return pthread_rwlock_unlock(l);
}

pthread_rwlock_tたとえば、構造体/クラス/その他のメンバーとして、保存されている場所の横にカウントを保持できます。

于 2011-04-23T21:31:52.837 に答える