Readers-writer ๋ฝ
Readers-writer ๋ฝ(RW Lock)์ ์ฝ๊ธฐ๋ง ์ํํ๋ ํ๋ก์ธ์ค์ ์ฐ๊ธฐ๋ง ์ํํ๋ ํ๋ก์ธ์ค๋ฅผ ๋ถ๋ฆฌํ๋ ๋ฐฉ์์ ๋๊ธฐ ์ฒ๋ฆฌ ๊ธฐ๋ฒ์ด๋ค. RW ๋ฝ์ ๊ฒฝ์ ์ํ๊ฐ ๋ฐ์ํ๋ ์ด์ ๋ ์ฐ๊ธฐ ์ฐ์ฐ ๋๋ฌธ์ด๋ฉฐ, ์ฐ๊ธฐ๋ง ๋ฐฐํ์ ์ผ๋ก ์ํํ๋ฉด ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ง ์๋๋ค๋ ๊ด์ฐฐ์ ๊ธฐ๋ฐํ๋ค.
RW ๋ฝ์ ๋ค์ ์ ์ฝ์ ๋ง์กฑํ๋๋ก ๋ฐฐํ ์ ์ด๋ฅผ ์ํํ๋ค.
- ๋ฝ์ ํ๋ฑ ์ค์ธ reader๋ ๊ฐ์ ์๊ฐ์ 0๊ฐ ์ด์ ์กด์ฌํ ์ ์๋ค.
- ๋ฝ์ ํ๋ ์ค์ธ writer๋ ๊ฐ์ ์๊ฐ์ 1๊ฐ๋ง ์กด์ฌํ ์ ์๋ค.
- reader์ writer๋ ๊ฐ์ ์๊ฐ์ ๋ฝ ํ๋ ์ํ๊ฐ ๋ ์ ์๋ค.
์คํ๋ฝ ๊ธฐ๋ฐ RW ๋ฝ ๊ตฌํ
void rwloack_read_acquire(int *rcnt, volatile int *wcnt) {
while (1) {
while (*wcnt); // writer๊ฐ ์์ผ๋ฉด ๋๊ธฐํ๋ค.
__sync_fetch_and_add(rcnt, 1);
if (*wcnt == 0) { // writer๊ฐ ์์ผ๋ฉด ๋ฝ์ ํ๋ํ๋ค.
break;
}
__sync_fetch_and_sub(rcnt, 1)
}
}
void rwlock_read_release(int *rcnt) {
__sync_fetch_and_sub(rcnt, 1);
}
void rwlock_write_acquire(bool *lock, volatile int *rcnt, int *wcnt) {
__sync_fetch_and_add(wcnt, 1);
while (*rcnt); // reader๊ฐ ์์ผ๋ฉด ๋๊ธฐํ๋ค.
spinlock_acquire(lock);
}
void rwlock_write_release(bool *lock, int *wcnt) {
spinlock_release(lock);
__sync_fetch_and_sub(wcnt, 1);
}
int rcnt = 0;
int wcnt = 0;
bool lock = false;
void reader() {
while (1) {
rwlock_read_acquire(&rcnt, &wcnt);
// critical section (read only)
rwlock_read_release(&rcnt);
}
}
void writer() {
while (1) {
rwlock_write_acquire(&lock, &rcnt, &wcnt);
// critical section (write only)
rwlock_write_release(&lock, &wcnt);
}
}
๋ฌ์คํธ์์ RW ๋ฝ ์ฌ์ฉ
use std::sync::RwLock;
fn main() {
let lock = RwLock::new(10);
{
// ์ด๋ฎคํฐ๋ธํ ์ฐธ์กฐ(reader)๋ฅผ ์ป๋๋ค.
let v1 = lock.read().unwrap();
let v2 = lock.read().unwrap();
println!("{} {}", v1, v2); // ์ฝ๊ธฐ ๋์
}
{
v = lock.write().unwrap(); // ๋ฎคํฐ๋ธํ ์ฐธ์กฐ(writer)๋ฅผ ์ป๋๋ค.
*v = 7; // ์ฐ๊ธฐ ๋์
println!("{}", v); // ์ฝ๊ธฐ ๋์
}
}