Rust 5 - 스마트 포인터, 병렬 프로그래밍, 레이온
32892 단어 rust
스택 대 힙
스택은 함수가 끝날 때 정리됩니다. 힙 청소에 대한 지침은 컴파일러에 의해 추가된 Rust에 있습니다.
포인터 대 스마트 포인터
포인터 - 메모리 주소를 저장하고 메모리의 위치를 참조하는 객체
스마트 포인터 - 다른 메타데이터를 저장하고 추가 기능을 제공하면서 포인터를 시뮬레이션합니다.
스마트 포인터는 Deref 및 Drop 특성을 구현합니다.
스마트 포인터
상자
fn main() {
let b = Box::new(5);
// uses 'Deref coercion' - converts a type into a reference to another type
println!("b = {}", b);
}
fn main() {
let x = 5;
let y = Box::new(x);
assert_eq!(5, x);
assert_eq!(5, *y);
}
하락
struct CustomSmartPointer {
data: String,
}
impl Drop for CustomSmartPointer {
fn drop(&mut self) {
println!("Dropping CustomSmartPointer with data `{}`!", self.data);
}
}
fn main() {
let c = CustomSmartPointer {
data: String::from("my stuff"),
};
let d = CustomSmartPointer {
data: String::from("other stuff"),
};
println!("CustomSmartPointers created.");
}
개체를 수동으로 놓을 수 있습니다.
fn main() {
let c = CustomSmartPointer {
data: String::from("some data"),
};
println!("CustomSmartPointer created.");
drop(c);
println!("CustomSmartPointer dropped before the end of main.");
}
Rc - 참조 카운트 스마트 포인터
개체의 여러 소유자가 필요한 경우(그래프 - 다른 노드에 가장자리가 있는 한 노드를 해제할 수 없음).
리스프와 같은 목록:
enum List {
Cons(i32, Rc<List>),
Nil,
}
use crate::List::{Cons, Nil};
use std::rc::Rc;
fn main() {
let a = Rc::new(Cons(5, Rc::new(Cons(10, Rc::new(Nil)))));
let b = Cons(3, Rc::clone(&a));
let c = Cons(4, Rc::clone(&a));
}
RefCell
Box와 달리 한 명의 소유자만 런타임에 소유권을 확인합니다.
pub trait Messenger {
fn send(&self, msg: &str);
}
pub struct LimitTracker<'a, T: Messenger> {
messenger: &'a T,
value: usize,
max: usize,
}
impl<'a, T> LimitTracker<'a, T>
where
T: Messenger,
{
pub fn new(messenger: &T, max: usize) -> LimitTracker<T> {
LimitTracker {
messenger,
value: 0,
max,
}
}
pub fn set_value(&mut self, value: usize) {
self.value = value;
let percentage_of_max = self.value as f64 / self.max as f64;
if percentage_of_max >= 1.0 {
self.messenger.send("Error: You are over your quota!");
} else if percentage_of_max >= 0.9 {
self.messenger
.send("Urgent warning: You've used up over 90% of your quota!");
} else if percentage_of_max >= 0.75 {
self.messenger
.send("Warning: You've used up over 75% of your quota!");
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::cell::RefCell;
struct MockMessenger {
sent_messages: RefCell<Vec<String>>,
}
impl MockMessenger {
fn new() -> MockMessenger {
MockMessenger {
sent_messages: RefCell::new(vec![]),
}
}
}
impl Messenger for MockMessenger {
fn send(&self, message: &str) {
self.sent_messages.borrow_mut().push(String::from(message));
}
}
#[test]
fn it_sends_an_over_75_percent_warning_message() {
let mock_messenger = MockMessenger::new();
let mut limit_tracker = LimitTracker::new(&mock_messenger, 100);
limit_tracker.set_value(80);
assert_eq!(mock_messenger.sent_messages.borrow().len(), 1);
}
}
스레드
use std::thread;
use std::time::Duration;
fn main() {
thread::spawn(|| {
for i in 1..10 {
println!("hi number {} from the spawned thread!", i);
thread::sleep(Duration::from_millis(1));
}
});
for i in 1..5 {
println!("hi number {} from the main thread!", i);
thread::sleep(Duration::from_millis(1));
}
}
스레드 조인
use std::thread;
use std::time::Duration;
fn main() {
let handle = thread::spawn(|| {
for i in 1..10 {
println!("hi number {} from the spawned thread!", i);
thread::sleep(Duration::from_millis(1));
}
});
for i in 1..5 {
println!("hi number {} from the main thread!", i);
thread::sleep(Duration::from_millis(1));
}
handle.join().unwrap();
}
스레드 간 데이터 전송
use std::sync::mpsc;
use std::thread;
fn main() {
let (sender, receiver) = mpsc::channel();
thread::spawn(move || {
let val = String::from("hi");
sender.send(val).unwrap();
});
let received = receiver.recv().unwrap();
println!("Got: {}", received);
}
뮤텍스
use std::sync::Mutex;
fn main() {
let m = Mutex::new(5);
{
let mut num = m.lock().unwrap();
*num = 6;
}
println!("m = {:?}", m);
}
아크 - 원자적으로 참조 카운트됨
스레드로부터 안전한 참조 카운팅 포인터입니다.
use std::sync::{Arc, Mutex};
use std::thread;
fn main() {
let counter = Arc::new(Mutex::new(0));
let mut handles = vec![];
for _ in 0..10 {
let counter = Arc::clone(&counter);
let handle = thread::spawn(move || {
let mut num = counter.lock().unwrap();
*num += 1;
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
println!("Result: {}", *counter.lock().unwrap());
}
레이온 라이브러리
[dependencies]
rayon = "1.4"
use rayon::prelude::*;
use std::borrow::Borrow;
/// Computes product of elements in vector in parallel
fn product_of_vec(input: &[i32]) -> i32 {
input.par_iter()
.map(|&i| i * i)
.sum()
}
fn main() {
let product = product_of_vec(vec![2, 4, 6].borrow());
println!("Product is {}", product);
}
채널과 결합
use std::sync::mpsc::channel;
use rayon::prelude::*;
fn main() {
let (sender, receiver) = channel();
(0..5).into_par_iter().for_each_with(sender, |s, x| s.send(x).unwrap());
let mut res: Vec<_> = receiver.iter().collect();
res.sort();
assert_eq!(&res[..], &[0, 1, 2, 3, 4])
}
수업 과정
식사 철학자
소개
컴퓨터 과학에서 식사하는 철학자 문제는 동기화 문제와 이를 해결하기 위한 기술을 설명하기 위해 동시 알고리즘 설계에서 자주 사용되는 예제 문제입니다.
이 문제here에 대한 자세한 내용을 읽을 수 있습니다.
일
fn main() {
let b = Box::new(5);
// uses 'Deref coercion' - converts a type into a reference to another type
println!("b = {}", b);
}
fn main() {
let x = 5;
let y = Box::new(x);
assert_eq!(5, x);
assert_eq!(5, *y);
}
struct CustomSmartPointer {
data: String,
}
impl Drop for CustomSmartPointer {
fn drop(&mut self) {
println!("Dropping CustomSmartPointer with data `{}`!", self.data);
}
}
fn main() {
let c = CustomSmartPointer {
data: String::from("my stuff"),
};
let d = CustomSmartPointer {
data: String::from("other stuff"),
};
println!("CustomSmartPointers created.");
}
fn main() {
let c = CustomSmartPointer {
data: String::from("some data"),
};
println!("CustomSmartPointer created.");
drop(c);
println!("CustomSmartPointer dropped before the end of main.");
}
enum List {
Cons(i32, Rc<List>),
Nil,
}
use crate::List::{Cons, Nil};
use std::rc::Rc;
fn main() {
let a = Rc::new(Cons(5, Rc::new(Cons(10, Rc::new(Nil)))));
let b = Cons(3, Rc::clone(&a));
let c = Cons(4, Rc::clone(&a));
}
pub trait Messenger {
fn send(&self, msg: &str);
}
pub struct LimitTracker<'a, T: Messenger> {
messenger: &'a T,
value: usize,
max: usize,
}
impl<'a, T> LimitTracker<'a, T>
where
T: Messenger,
{
pub fn new(messenger: &T, max: usize) -> LimitTracker<T> {
LimitTracker {
messenger,
value: 0,
max,
}
}
pub fn set_value(&mut self, value: usize) {
self.value = value;
let percentage_of_max = self.value as f64 / self.max as f64;
if percentage_of_max >= 1.0 {
self.messenger.send("Error: You are over your quota!");
} else if percentage_of_max >= 0.9 {
self.messenger
.send("Urgent warning: You've used up over 90% of your quota!");
} else if percentage_of_max >= 0.75 {
self.messenger
.send("Warning: You've used up over 75% of your quota!");
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::cell::RefCell;
struct MockMessenger {
sent_messages: RefCell<Vec<String>>,
}
impl MockMessenger {
fn new() -> MockMessenger {
MockMessenger {
sent_messages: RefCell::new(vec![]),
}
}
}
impl Messenger for MockMessenger {
fn send(&self, message: &str) {
self.sent_messages.borrow_mut().push(String::from(message));
}
}
#[test]
fn it_sends_an_over_75_percent_warning_message() {
let mock_messenger = MockMessenger::new();
let mut limit_tracker = LimitTracker::new(&mock_messenger, 100);
limit_tracker.set_value(80);
assert_eq!(mock_messenger.sent_messages.borrow().len(), 1);
}
}
use std::thread;
use std::time::Duration;
fn main() {
thread::spawn(|| {
for i in 1..10 {
println!("hi number {} from the spawned thread!", i);
thread::sleep(Duration::from_millis(1));
}
});
for i in 1..5 {
println!("hi number {} from the main thread!", i);
thread::sleep(Duration::from_millis(1));
}
}
스레드 조인
use std::thread;
use std::time::Duration;
fn main() {
let handle = thread::spawn(|| {
for i in 1..10 {
println!("hi number {} from the spawned thread!", i);
thread::sleep(Duration::from_millis(1));
}
});
for i in 1..5 {
println!("hi number {} from the main thread!", i);
thread::sleep(Duration::from_millis(1));
}
handle.join().unwrap();
}
스레드 간 데이터 전송
use std::sync::mpsc;
use std::thread;
fn main() {
let (sender, receiver) = mpsc::channel();
thread::spawn(move || {
let val = String::from("hi");
sender.send(val).unwrap();
});
let received = receiver.recv().unwrap();
println!("Got: {}", received);
}
뮤텍스
use std::sync::Mutex;
fn main() {
let m = Mutex::new(5);
{
let mut num = m.lock().unwrap();
*num = 6;
}
println!("m = {:?}", m);
}
아크 - 원자적으로 참조 카운트됨
스레드로부터 안전한 참조 카운팅 포인터입니다.
use std::sync::{Arc, Mutex};
use std::thread;
fn main() {
let counter = Arc::new(Mutex::new(0));
let mut handles = vec![];
for _ in 0..10 {
let counter = Arc::clone(&counter);
let handle = thread::spawn(move || {
let mut num = counter.lock().unwrap();
*num += 1;
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
println!("Result: {}", *counter.lock().unwrap());
}
레이온 라이브러리
[dependencies]
rayon = "1.4"
use rayon::prelude::*;
use std::borrow::Borrow;
/// Computes product of elements in vector in parallel
fn product_of_vec(input: &[i32]) -> i32 {
input.par_iter()
.map(|&i| i * i)
.sum()
}
fn main() {
let product = product_of_vec(vec![2, 4, 6].borrow());
println!("Product is {}", product);
}
채널과 결합
use std::sync::mpsc::channel;
use rayon::prelude::*;
fn main() {
let (sender, receiver) = channel();
(0..5).into_par_iter().for_each_with(sender, |s, x| s.send(x).unwrap());
let mut res: Vec<_> = receiver.iter().collect();
res.sort();
assert_eq!(&res[..], &[0, 1, 2, 3, 4])
}
수업 과정
식사 철학자
소개
컴퓨터 과학에서 식사하는 철학자 문제는 동기화 문제와 이를 해결하기 위한 기술을 설명하기 위해 동시 알고리즘 설계에서 자주 사용되는 예제 문제입니다.
이 문제here에 대한 자세한 내용을 읽을 수 있습니다.
일
[dependencies]
rayon = "1.4"
use rayon::prelude::*;
use std::borrow::Borrow;
/// Computes product of elements in vector in parallel
fn product_of_vec(input: &[i32]) -> i32 {
input.par_iter()
.map(|&i| i * i)
.sum()
}
fn main() {
let product = product_of_vec(vec![2, 4, 6].borrow());
println!("Product is {}", product);
}
use std::sync::mpsc::channel;
use rayon::prelude::*;
fn main() {
let (sender, receiver) = channel();
(0..5).into_par_iter().for_each_with(sender, |s, x| s.send(x).unwrap());
let mut res: Vec<_> = receiver.iter().collect();
res.sort();
assert_eq!(&res[..], &[0, 1, 2, 3, 4])
}
식사 철학자
소개
컴퓨터 과학에서 식사하는 철학자 문제는 동기화 문제와 이를 해결하기 위한 기술을 설명하기 위해 동시 알고리즘 설계에서 자주 사용되는 예제 문제입니다.
이 문제here에 대한 자세한 내용을 읽을 수 있습니다.
일
임의의 밀리초 동안 휴면
두 스틱의 잠금 해제
임의의 밀리초 동안 휴면
모든 스레드 조인
보너스
std::sync::mpsc::channel
를 사용하여 모든 메시지를 먼저 수집합니다해결책
Dining philosophers
GitHub에서 내 학습 Rust 저장소를 확인하세요!
펫7555 / 학습-녹
Reference
이 문제에 관하여(Rust 5 - 스마트 포인터, 병렬 프로그래밍, 레이온), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/petr7555/rust-5-smart-pointers-parallel-programming-rayon-16nd텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)