1. 뮤텍스는 단일 자원을 보호하는데 사용
이때 단점은 다른 스레드 자원해제 될 때까지 무한히 대기하는 상황이 발생해 DeadLock이 발생한다. (정보처리기사 실기 운영체제 파트 공부를 하면서 나온내용이다!!!)
use std::thread;
use std::sync::Mutex;
// counter를 전역변수로 지정
static counter: Mutex<i32> = Mutex::new(0);
// counter에 접근할 때 뮤텍스로 잠금해서 상호베제를 한다.
fn inc_counter() {
let mut num = counter.lock().unwrap();
*num = *num +1;
}
fn main(){
// 스레드를 저장할 벡터 생성
let mut thread_vec = vec![];
for _ in 0..100{
let th = thread::spawn(inc_counter);
thread_vec.push(th);
}
for th in thread_vec {
th.join().unwrap() // join은 모든 스레드의 종료를 대기
}
// 100을 출력한다
println!("결과: {}", *counter.lock().unwrap());
}
2. 세마포어는 스레드를 넘어 프로세스간의 공유 자원을 보호하는데도 사용한다. acquire_onwed 메서드를 통해 허가를 획득하고 drop으로 해제한 다음 다른 비동기 프로세스가 또 허가를 받아 실행한다.
use std::sync::{Arc,Mutex};
use tokio::sync::Semaphore;
// 전역변수 counter
static counter:Mutex<i32> = Mutex::new(0);
#[tokio::main]
async fn main(){
// 동시에 2개의 스레드가 접근하도록 세마포어 설정
let semaphore = Arc::new(Semaphore::new(2));
// 세마포어를 저장할 벡터 생성!
let mut future_vec = vec![];
for _ in 0..100 {
// acquire_owned는 세마포어 허가를 위한 메서드
let permit = semaphore.clone().acquire_owned().await.unwrap();
let future = tokio::spawn(async move{
// move를 통해 전역변수인 counter와 permit변수의 소유권을 가져온다.
// 뮤텍스를 사용해 카운터를 잠금해서 자원이 해체될 때 까지 대기상태에 놓인다.
let mut num = counter.lock().unwrap();
*num = *num +1;
// 세마포어를 해제한다.
drop(permit);
});
// 세마포어를 벡터에 담는다.
future_vec.push(future)
}
for future in future_vec {
// 비동기 작업이 끝날때까지 기다린다.
future.await.unwrap();
}
// 100을 출력한다
println!("결과: {}", *counter.lock().unwrap())
}
참고한 공식문서와 책
https://docs.rs/tokio/latest/tokio/sync/struct.Semaphore.html#method.acquire_owned
https://www.yes24.com/Product/Goods/125028287
'Rust' 카테고리의 다른 글
Bufreader read_line()으로 파일 한줄씩 읽고 바이트 반환, Cursor 로 Read 구현 (0) | 2024.08.16 |
---|---|
러스트로 리눅스 wc명령어 구현 (0) | 2024.08.14 |
Rust 아토믹(atomic)연산 스레드 (0) | 2024.02.04 |
Rust 스레드 파킹 (0) | 2024.02.04 |
Rust 스레드 조건 변수 대기와 알림 (0) | 2024.02.04 |