マイナスの副作用なしに両方を次々に呼び出すことはできますか?
確かに違います!これを想像してみてください:
thread A thread B:
down_write
down_read (blocked)
...
unlock
|\ up_write
| (released, acquired read lock)
| ...
\ up_read (lock messed up)
私はこれまで使用rw_semaphore
したことがありませんが、シングルライター-マルチリーダーロックの場合は、これが解決策です。
編集:これには、ロックが再帰的である必要があることに注意してください。それが実際に再帰的ではないrw_semaphore
ことが判明した場合。
ロックが読み取りモードまたは書き込みモードのどちらでロックされているかを検出できれば、問題は簡単に解決できます(これらのモードのいずれかでロックされている、つまりロックが解除されていないことがすでにわかっている場合)。
ロックはマルチリーダーであるため、read-try-lockを使用して状況を知ることができます。
if (down_read_trylock(sem))
/* semaphore was locked in read mode */
else
/* semaphore was locked in write mode */
このif
場合、セマフォはすでに読み取りモードでロックされており、再度ロックしたため、2 up_read
秒必要です。それ以外の場合、セマフォは書き込みモードでロックされているため、1つ必要up_write
です。down_read_trylock
これは、最大数の読み取りロックに到達したこと、またはロックが書き込みモードでロックされていることを除いて、その他の理由で失敗しないことを前提としています。
結論として:
void unlock(struct rw_semaphore *sem)
{
if (down_read_trylock(sem))
{
up_read(sem);
up_read(sem);
}
else
up_write(sem);
}
注:使用前にテストしてください!