Rust의 스레드 안전
17229 단어 Rust
목적
스레드 안전을 어떻게 실현하는지 알아보기
요약
① 스레드간에 데이터가 원래 공유되지 않도록 한다.
②스레드간에 공유되는 경우는 같은 영역에 같은 타이밍으로 액세스하는 일이 없는지를 컴파일시에 체크해 준다.
스레드
thread::spawn(|arg|{body}); 에서 사용한다.
qiita.rsuse std::thread;
fn main() {
let handle = thread::spawn(|| {
println!("1", );
});
println!("2", );
}
실행 결과
10개의 스레드 실행. 어느 순서로 실행되는지는 모른다.
qiita.rsuse std::thread;
fn main() {
let mut handles=Vec::new();
for x in 0..10{
handles.push(thread::spawn(move || {
println!("{}", x);//moveさせないと参照のスコープから外れてしまう。
}))
}
for handle in handles{
let _=handle.join();//joinは実行完了まで
}
}
스레드간에 데이터 공유
스레드간에 데이터를 공유하지 않음
data라고 하는 vector의 값을 thread 마다 +1 하는 처리.
다음은 스레드간에 데이터를 공유할 때 안전하지 않으면 컴파일 오류가 되는 예입니다.
qiita.rsuse std::thread;
fn main() {
let mut data=[0,1];//共有データ
let mut handles=Vec::new();
for x in 0..2{
handles.push(thread::spawn(move || {
data[x]+=1;
println!("{}", x);
}))
}
for handle in handles{
let _=handle.join();//joinは実行完了まで
}
}
다음과 같이 첫 번째 스레드가 실행될 때 data의 소유권이 첫 번째 스레드로 마이그레이션됩니다. 다른 스레드에서 사용할 수 없습니다.
소유권을 공유하는 메커니즘
소유권을 공유하기 위해 Rc라는 참조 카운터 식 스마트 포인터가 있습니다.
C++의 shared_ptr 마찬가지로 참조 카운터가 0이 되면 자동적으로 해제된다.
디폴트는 불변.
qiita.rsuse std::rc::Rc;
fn main() {
let data=Rc::new([0,1]);
println!("参照数 {}", Rc::strong_count(&data));//1
{
let data2=data.clone();//参照カウントUP
println!("参照数 {}", Rc::strong_count(&data));//2
for x in 0..2{
println!("{}", data2[x]);
}
}//解放
println!("参照数 {}", Rc::strong_count(&data));//1
}
Rc를 사용하여 데이터 공유하기
qiita.rsuse std::rc::Rc;
use std::thread;
fn main() {
let mut handles=Vec::new();
let mut data=Rc::new([0,1]);//共有データ
for x in 0..2{
let mut ref_data=data.clone();//参照カウントUP
handles.push(thread::spawn(move || {
ref_data[x]+=1;
println!("{}", ref_data[x]);
}))
}
for handle in handles{
let _=handle.join();//joinは実行完了まで
}
}
데이터를 스레드간에 안전하게 전달할 수 없으면 오류가 발생합니다. Rc는 멀티스레드에서는 사용할 수 없다.
멀티스레드 때 다른 스레드에 방해받지 않고 제대로 참조를 카운트업하거나 카운트다운할 수 있는 것을 확인할 수 없었기 때문이다.
멀티 스레드에서도 사용할 수있는 스마트 포인터 Arc (Automatically Reference Counted).
Rc를 Arc로 바꾸어 컴파일.
qiita.rsuse std::sync::Arc;
use std::thread;
fn main() {
let mut handles=Vec::new();
let mut data=Arc::new([0,1]);//共有データ
for x in 0..2{
let mut ref_data=data.clone();//参照カウントUP
handles.push(thread::spawn(move || {
ref_data[x]+=1;
println!("{}", ref_data[x]);
}))
}
for handle in handles{
let _=handle.join();//joinは実行完了まで
}
}
Arc은 다시 쓸 수 없을 때 화난다.
ref_data[x/2]+=1일 때, 스레드 0과 1에서는 같은 영역에 액세스하여 경합이 일어날 가능성이 있기 때문에 에러가 되고 있다.
Mutex를 사용하여 하나의 스레드에서 데이터 액세스를 허용합니다.
lock()을 사용하면 데이터에 대한 잠금과 해제가 자동으로 이루어져 충돌이 일어나지 않는 것이 보장된다.
qiita.rs
use std::sync::{Arc,Mutex};
use std::thread;
fn main() {
let mut handles=Vec::new();
let mut data=Arc::new(Mutex::new([0,1]));//共有データ
for x in 0..2{
let ref_data=data.clone();//参照カウントUP
handles.push(thread::spawn(move || {
let mut data=ref_data.lock().unwrap();
data[x]+=1;
println!("{}", data[x]);
}))
}
for handle in handles{
let _=handle.join();//joinは実行完了まで
}
}
실행 결과
Reference
이 문제에 관하여(Rust의 스레드 안전), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/asparagasu/items/c25c7e9b2e5389daee8a
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
① 스레드간에 데이터가 원래 공유되지 않도록 한다.
②스레드간에 공유되는 경우는 같은 영역에 같은 타이밍으로 액세스하는 일이 없는지를 컴파일시에 체크해 준다.
스레드
thread::spawn(|arg|{body}); 에서 사용한다.
qiita.rsuse std::thread;
fn main() {
let handle = thread::spawn(|| {
println!("1", );
});
println!("2", );
}
실행 결과
10개의 스레드 실행. 어느 순서로 실행되는지는 모른다.
qiita.rsuse std::thread;
fn main() {
let mut handles=Vec::new();
for x in 0..10{
handles.push(thread::spawn(move || {
println!("{}", x);//moveさせないと参照のスコープから外れてしまう。
}))
}
for handle in handles{
let _=handle.join();//joinは実行完了まで
}
}
스레드간에 데이터 공유
스레드간에 데이터를 공유하지 않음
data라고 하는 vector의 값을 thread 마다 +1 하는 처리.
다음은 스레드간에 데이터를 공유할 때 안전하지 않으면 컴파일 오류가 되는 예입니다.
qiita.rsuse std::thread;
fn main() {
let mut data=[0,1];//共有データ
let mut handles=Vec::new();
for x in 0..2{
handles.push(thread::spawn(move || {
data[x]+=1;
println!("{}", x);
}))
}
for handle in handles{
let _=handle.join();//joinは実行完了まで
}
}
다음과 같이 첫 번째 스레드가 실행될 때 data의 소유권이 첫 번째 스레드로 마이그레이션됩니다. 다른 스레드에서 사용할 수 없습니다.
소유권을 공유하는 메커니즘
소유권을 공유하기 위해 Rc라는 참조 카운터 식 스마트 포인터가 있습니다.
C++의 shared_ptr 마찬가지로 참조 카운터가 0이 되면 자동적으로 해제된다.
디폴트는 불변.
qiita.rsuse std::rc::Rc;
fn main() {
let data=Rc::new([0,1]);
println!("参照数 {}", Rc::strong_count(&data));//1
{
let data2=data.clone();//参照カウントUP
println!("参照数 {}", Rc::strong_count(&data));//2
for x in 0..2{
println!("{}", data2[x]);
}
}//解放
println!("参照数 {}", Rc::strong_count(&data));//1
}
Rc를 사용하여 데이터 공유하기
qiita.rsuse std::rc::Rc;
use std::thread;
fn main() {
let mut handles=Vec::new();
let mut data=Rc::new([0,1]);//共有データ
for x in 0..2{
let mut ref_data=data.clone();//参照カウントUP
handles.push(thread::spawn(move || {
ref_data[x]+=1;
println!("{}", ref_data[x]);
}))
}
for handle in handles{
let _=handle.join();//joinは実行完了まで
}
}
데이터를 스레드간에 안전하게 전달할 수 없으면 오류가 발생합니다. Rc는 멀티스레드에서는 사용할 수 없다.
멀티스레드 때 다른 스레드에 방해받지 않고 제대로 참조를 카운트업하거나 카운트다운할 수 있는 것을 확인할 수 없었기 때문이다.
멀티 스레드에서도 사용할 수있는 스마트 포인터 Arc (Automatically Reference Counted).
Rc를 Arc로 바꾸어 컴파일.
qiita.rsuse std::sync::Arc;
use std::thread;
fn main() {
let mut handles=Vec::new();
let mut data=Arc::new([0,1]);//共有データ
for x in 0..2{
let mut ref_data=data.clone();//参照カウントUP
handles.push(thread::spawn(move || {
ref_data[x]+=1;
println!("{}", ref_data[x]);
}))
}
for handle in handles{
let _=handle.join();//joinは実行完了まで
}
}
Arc은 다시 쓸 수 없을 때 화난다.
ref_data[x/2]+=1일 때, 스레드 0과 1에서는 같은 영역에 액세스하여 경합이 일어날 가능성이 있기 때문에 에러가 되고 있다.
Mutex를 사용하여 하나의 스레드에서 데이터 액세스를 허용합니다.
lock()을 사용하면 데이터에 대한 잠금과 해제가 자동으로 이루어져 충돌이 일어나지 않는 것이 보장된다.
qiita.rs
use std::sync::{Arc,Mutex};
use std::thread;
fn main() {
let mut handles=Vec::new();
let mut data=Arc::new(Mutex::new([0,1]));//共有データ
for x in 0..2{
let ref_data=data.clone();//参照カウントUP
handles.push(thread::spawn(move || {
let mut data=ref_data.lock().unwrap();
data[x]+=1;
println!("{}", data[x]);
}))
}
for handle in handles{
let _=handle.join();//joinは実行完了まで
}
}
실행 결과
Reference
이 문제에 관하여(Rust의 스레드 안전), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/asparagasu/items/c25c7e9b2e5389daee8a
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
use std::thread;
fn main() {
let handle = thread::spawn(|| {
println!("1", );
});
println!("2", );
}
use std::thread;
fn main() {
let mut handles=Vec::new();
for x in 0..10{
handles.push(thread::spawn(move || {
println!("{}", x);//moveさせないと参照のスコープから外れてしまう。
}))
}
for handle in handles{
let _=handle.join();//joinは実行完了まで
}
}
스레드간에 데이터를 공유하지 않음
data라고 하는 vector의 값을 thread 마다 +1 하는 처리.
다음은 스레드간에 데이터를 공유할 때 안전하지 않으면 컴파일 오류가 되는 예입니다.
qiita.rs
use std::thread;
fn main() {
let mut data=[0,1];//共有データ
let mut handles=Vec::new();
for x in 0..2{
handles.push(thread::spawn(move || {
data[x]+=1;
println!("{}", x);
}))
}
for handle in handles{
let _=handle.join();//joinは実行完了まで
}
}
다음과 같이 첫 번째 스레드가 실행될 때 data의 소유권이 첫 번째 스레드로 마이그레이션됩니다. 다른 스레드에서 사용할 수 없습니다.
소유권을 공유하는 메커니즘
소유권을 공유하기 위해 Rc라는 참조 카운터 식 스마트 포인터가 있습니다.
C++의 shared_ptr 마찬가지로 참조 카운터가 0이 되면 자동적으로 해제된다.
디폴트는 불변.
qiita.rs
use std::rc::Rc;
fn main() {
let data=Rc::new([0,1]);
println!("参照数 {}", Rc::strong_count(&data));//1
{
let data2=data.clone();//参照カウントUP
println!("参照数 {}", Rc::strong_count(&data));//2
for x in 0..2{
println!("{}", data2[x]);
}
}//解放
println!("参照数 {}", Rc::strong_count(&data));//1
}
Rc를 사용하여 데이터 공유하기
qiita.rs
use std::rc::Rc;
use std::thread;
fn main() {
let mut handles=Vec::new();
let mut data=Rc::new([0,1]);//共有データ
for x in 0..2{
let mut ref_data=data.clone();//参照カウントUP
handles.push(thread::spawn(move || {
ref_data[x]+=1;
println!("{}", ref_data[x]);
}))
}
for handle in handles{
let _=handle.join();//joinは実行完了まで
}
}
데이터를 스레드간에 안전하게 전달할 수 없으면 오류가 발생합니다. Rc는 멀티스레드에서는 사용할 수 없다.
멀티스레드 때 다른 스레드에 방해받지 않고 제대로 참조를 카운트업하거나 카운트다운할 수 있는 것을 확인할 수 없었기 때문이다.
멀티 스레드에서도 사용할 수있는 스마트 포인터 Arc (Automatically Reference Counted).
Rc를 Arc로 바꾸어 컴파일.
qiita.rs
use std::sync::Arc;
use std::thread;
fn main() {
let mut handles=Vec::new();
let mut data=Arc::new([0,1]);//共有データ
for x in 0..2{
let mut ref_data=data.clone();//参照カウントUP
handles.push(thread::spawn(move || {
ref_data[x]+=1;
println!("{}", ref_data[x]);
}))
}
for handle in handles{
let _=handle.join();//joinは実行完了まで
}
}
Arc은 다시 쓸 수 없을 때 화난다.
ref_data[x/2]+=1일 때, 스레드 0과 1에서는 같은 영역에 액세스하여 경합이 일어날 가능성이 있기 때문에 에러가 되고 있다.
Mutex를 사용하여 하나의 스레드에서 데이터 액세스를 허용합니다.
lock()을 사용하면 데이터에 대한 잠금과 해제가 자동으로 이루어져 충돌이 일어나지 않는 것이 보장된다.
qiita.rs
use std::sync::{Arc,Mutex};
use std::thread;
fn main() {
let mut handles=Vec::new();
let mut data=Arc::new(Mutex::new([0,1]));//共有データ
for x in 0..2{
let ref_data=data.clone();//参照カウントUP
handles.push(thread::spawn(move || {
let mut data=ref_data.lock().unwrap();
data[x]+=1;
println!("{}", data[x]);
}))
}
for handle in handles{
let _=handle.join();//joinは実行完了まで
}
}
실행 결과
Reference
이 문제에 관하여(Rust의 스레드 안전), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/asparagasu/items/c25c7e9b2e5389daee8a텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)