use std::thread;
fn main() {
let handle = thread::spawn(|| {
println!("new thread");
});
handle.join().unwrap();
}
use std::thread;
fn main() {
let handle = thread::spawn(|| {
panic!("panic occured on thread")
});
match handle.join() {
Ok(_) => {},
Err(e) => {
println!("Error occured inside of thread"); // 출력
}
}
println!("process finised"); // 출력
}
use std::{sync::mpsc, thread};
fn main() {
let (tx, rx) = mpsc::channel();
thread::spawn(move || {
tx.send(100).unwrap();
});
let data = rx.recv().unwrap();
println!("{}", data);
}
[package]
name = "myrust"
version = "0.1.0"
edition = "2024"
[dependencies]
futures = "0.3"
use futures::executor::block_on;
async fn hello_world() {
println!("hello world");
}
fn main() {
let future = hello_world();
println!("called on main");
block_on(future);
println!("future finished");
}
use futures::executor::block_on;
async fn calc_sum(start: i32, end: i32) -> i32 {
let mut sum = 0;
for i in start..=end {
sum += i;
}
sum
}
async fn calc() -> i32 {
let mut sum = 0;
sum += calc_sum(1, 50).await;
sum += calc_sum(51, 100).await;
sum
}
fn main() {
let fut = calc();
let sum = block_on(fut);
println!("{}", sum);
}
use std::{thread, time::Duration};
use futures::executor::block_on;
async fn sleep_10s() {
for _ in 1..10 {
print!(".");
thread::sleep(Duration::from_secs(1));
}
}
async fn print_loop() {
for i in 1..10 {
print!("{} ", i);
}
}
async fn wrapper() {
let f1 = sleep_10s();
let f2 = print_loop();
futures::join!(f1, f2);
}
fn main() {
let future = wrapper();
block_on(future); // => .........1 2 3 4 5 6 7 8 9 출력
}
join!으로 두개의 future가 같은 이벤트 루프를 공유하는 상황이다sleep_10s 함수의 sleep이, 다른 future인 print_loop도 막아버려 동시성을 가지지 못하게 되었다use std::{time::Duration};
use tokio::time;
async fn sleep_10s() {
for _ in 1..10 {
print!(".");
time::sleep(Duration::from_secs(1)).await; // tokio 적용 1
}
}
async fn print_loop() {
for i in 1..10 {
print!("{} ", i);
}
}
async fn wrapper() {
let f1 = sleep_10s();
let f2 = print_loop();
tokio::join!(f1, f2); // tokio 적용 2
}
#[tokio::main]
async fn main() {
wrapper().await; // => .1 2 3 4 5 6 7 8 9 ........ 출력
}
| 이벤트루프 | 스레드 | |
|---|---|---|
| 특징 | 단일 스레드를 사용 이벤트큐에 수신된 이벤트 처리를 무한 반복 | 스레드마다 별도의 작업이 할당됨 |
| 장점 | 최소한의 오버헤드로 많은 이벤트 처리 가능 복잡한 동기화 매커니즘 필요 없음 | cpu 코어가 충분한 경우 복수의 작업 병렬화 가능 |
| 단점 | 단일 스레드이므로, cpu 연산이 많이 필요한 작업에 부적합 | 복잡한 동기화 매커니즘이 필요함 cpu 개수보다 많은 동시 처리를 수행하는 경우 컨텍스트 스위칭으로 인한 오버헤드 발생 |
use std::{sync::Mutex, thread};
static counter: Mutex<i32> = Mutex::new(0);
fn inc_counter() {
let mut num = counter.lock().unwrap();
*num += 1;
}
fn main() {
let mut thread_vec = vec![];
for _ in 1..100 {
thread_vec.push(thread::spawn(inc_counter));
}
for th in thread_vec {
th.join().unwrap();
}
println!("{}", *counter.lock().unwrap());
}
use std::{sync::{Arc, Mutex}, thread, time::Duration};
use tokio::sync::Semaphore;
static counter: Mutex<i32> = Mutex::new(0);
#[tokio::main]
async fn main() {
let semaphore = Arc::new(Semaphore::new(2));
let mut future_vec = vec![];
for i in 1..100 {
let semaphore = semaphore.clone();
let future = tokio::spawn(async move {
let permit = semaphore.acquire_owned().await.unwrap();
println!("{} enter", i);
tokio::time::sleep(Duration::from_millis(100)).await;
let mut num = counter.lock().unwrap();
*num += 1;
drop(permit);
});
future_vec.push(future);
}
for th in future_vec {
th.await.unwrap();
}
println!("{}", *counter.lock().unwrap());
}
Arc<T>는 원자적 참조 카운트를 의미한다use std::{thread, sync::{Arc, Mutex}};
fn main() {
let lock_a = Arc::new(Mutex::new(0));
let lock_b = Arc::new(Mutex::new(0));
let lock_a_ref = lock_a.clone();
let lock_b_ref = lock_b.clone();
let thread1 = thread::spawn(move || { // 강제로 교착상태 만듬
let a = lock_a.lock().unwrap();
let b = lock_b_ref.lock().unwrap();
});
let thread2 = thread::spawn(move || {
let a = lock_a_ref.lock().unwrap();
let b = lock_b.lock().unwrap();
});
thread1.join().unwrap();
thread2.join().unwrap();
}