Rust Threads の安全性: C との比較。

Susan Sarandon
リリース: 2024-11-19 11:54:02
オリジナル
749 人が閲覧しました

この POC (概念実証) では、Rust 言語が 競合状態 をどのように扱うかを調査し、C 、広く使用されている言語ですが、競合するためのセキュリティ保証は少なくなります。

Rust Threads の安全性: A と C の比較

スレッドの安全性: C から Rust までのデータ競合

索引

    1. はじめに
  • 2. スレッド
  • 3. C での実装
    • 3.1.競合状態から保護されていないコード
    • 3.2.ミューテックスによる固定
  • 4. Rustでの実装
    • 4.1.競合状態の問題
    • 4.2. Mutex と Arc による解決
    • 4.3.ミューテックス vs. Rwロック
  • 5. 結論
  • 6. 参考文献

1. はじめに

コンピューティングでは、

スレッドは、ソフトウェアタスクを同時に実行できるサブタスクに分割するために使用されます。 スレッドを使用することで、処理時間を獲得し、マシンのリソースをより有効に活用できますが、この競争により、データに深刻な不整合が生じる可能性がある競合状態などの課題が生じます。


2. スレッド

スレッド は、タスクを同時に処理できるようにする実行単位です。以下の図に示すように、スレッドはプログラム内の独立した実行フローと考えることができます。

Rust Threads safety: Uma comparação com C.スレッドはパフォーマンス上の利点をもたらしますが、特に共有リソースにアクセスする場合にリスクが生じます。

さらに、スレッドを使用して並列処理を実装することもでき、複数のタスクが異なる CPU コアで同時に実行されます。これにより、プログラムは利用可能なハードウェアを有効に活用し、独立したタスクの実行を高速化できます。

3. C での実装

C

で簡単なシステムを作成しましょう:

初期残高は 1000 です。
  1. 貸方または借方となる一連のトランザクション。
  2. スレッドを使用したこれらのトランザクションの並列処理。
  3. 3.1.競合状態から保護されていないコード

int saldo = 1000; 

void creditar(int valor) {
    int tmp_saldo = saldo;

    sleep(1); // Delay simulado

    saldo += tmp_saldo + valor;
}

void debitar(int valor) {
    int temp = saldo;

    sleep(1); // Delay simulado

    if (temp >= valor) {
        saldo = temp - valor;
    }
}

void* processar_transacao(void* arg) {
    int valor = *(int*)arg;

    if (valor > 0) {
        creditar(valor);
    } else {
        debitar(abs(valor));
    }

    return NULL;
}

int main() {
    int transactions[] = {100, -50, 200, -150, 300, -200, 150, -100, 50, -50};
    int num_transactions = sizeof(transactions) / sizeof(transactions[0]);

    pthread_t threads[num_transactions];

    for (int i = 0; i < num_transactions; i++) {
        pthread_create(&threads[i], NULL, processar_transacao, &transactions[i]); // Cria uma thread para cada transação
    }

    for (int i = 0; i < num_transactions; i++) {
        pthread_join(threads[i], NULL); // Aguarda todas as threads terminarem
    }

    printf("Saldo final da conta: %d\n", saldo);
    return 0;
}
ログイン後にコピー
ログイン後にコピー
マルチスレッド処理

を備えた環境を選択すると、いわゆる競合状態が発生する可能性があります。2 つのスレッドが同じ値にアクセスして変更すると、競合状態が発生します。この問題は、呼び出し間の競合により、各スレッドでアクセスされる値の同期が保証されないために発生します。

このコードを複数回実行すると、スレッドが同時にアクセスしてバランスを変更するため、最終的なバランスは変化します。

Rust Threads safety: Uma comparação com C.


3.2.ミューテックスによる固定

int saldo = 1000; 

void creditar(int valor) {
    int tmp_saldo = saldo;

    sleep(1); // Delay simulado

    saldo += tmp_saldo + valor;
}

void debitar(int valor) {
    int temp = saldo;

    sleep(1); // Delay simulado

    if (temp >= valor) {
        saldo = temp - valor;
    }
}

void* processar_transacao(void* arg) {
    int valor = *(int*)arg;

    if (valor > 0) {
        creditar(valor);
    } else {
        debitar(abs(valor));
    }

    return NULL;
}

int main() {
    int transactions[] = {100, -50, 200, -150, 300, -200, 150, -100, 50, -50};
    int num_transactions = sizeof(transactions) / sizeof(transactions[0]);

    pthread_t threads[num_transactions];

    for (int i = 0; i < num_transactions; i++) {
        pthread_create(&threads[i], NULL, processar_transacao, &transactions[i]); // Cria uma thread para cada transação
    }

    for (int i = 0; i < num_transactions; i++) {
        pthread_join(threads[i], NULL); // Aguarda todas as threads terminarem
    }

    printf("Saldo final da conta: %d\n", saldo);
    return 0;
}
ログイン後にコピー
ログイン後にコピー

Mutex は、一度に 1 つのスレッドだけが共有リソースにアクセスできるようにする同期プリミティブです。 mutex の頭字語は、「相互排除」を意味する英語の用語 mutual exclusion に由来しています。

スレッドが ミューテックスを取得すると、同じミューテックスを取得しようとする他のスレッドは、最初のスレッドがミューテックスを解放するまで一時停止されます。これにより、2 つ以上のプロセス (スレッド) が共有リソースに同時にアクセスできなくなります。

Rust Threads safety: Uma comparação com C.

4. Rustでの実装

int saldo = 1000; 
pthread_mutex_t saldo_mutex; // Mutex para proteger o saldo

void creditar(int valor) { 
    pthread_mutex_lock(&saldo_mutex); // Bloqueia o mutex
    int tmp_saldo = saldo;

    sleep(1); // Delay simulado

    saldo = tmp_saldo + valor;

    pthread_mutex_unlock(&saldo_mutex); // Libera o mutex
}

void debitar(int valor) {
    pthread_mutex_lock(&saldo_mutex); // Bloqueia o mutex
    int tmp_saldo = saldo;

    sleep(1); // Delay simulado

    if (tmp_saldo >= valor) {
        saldo = tmp_saldo - valor;
    }

    pthread_mutex_unlock(&saldo_mutex);  // Libera o mutex
}
ログイン後にコピー

Rust を データ競合 のない言語として考えるのは生産的ではありませんが、構造体 とそのコンパイラがメモリとスレッドの安全性のための優れた機能をもたらすことでどのように貢献するのかは理解できます。

Rust は、所有権借用、同時実行安全構造などの機能を使用して、コンパイル時保証で 競合状態を処理します。

  • Arc: 不変データの安全な共有。
  • Mutex および RwLock: 可変データのアクセス制御。

4.1.競合状態の問題

Arc および Mutex 構造体を使用しない

Rust’s rich type system and ownership model guarantee memory-safety and thread-safety — enabling you to eliminate many classes of bugs at compile-time.
ログイン後にコピー

Rust では、保護せずに複数の スレッド から 可変 データ (バランス) に直接アクセスすることはできません。
安全なメカニズムなしで残高が複数のスレッド (handle1 および handle2) に移動されるため、コンパイラーはエラーを生成します。
表示されるエラーメッセージは次のとおりです:

fn main() {
    let mut saldo = 1000; // saldo mutável, mas sem proteção

    let handle1 = thread::spawn(move || {
        saldo += 100;  // erro: `saldo` é movido para esta thread sem proteção
    });

    let handle2 = thread::spawn(move || {
        saldo -= 50;  // erro: `saldo` é movido para esta thread sem proteção
    });

    handle1.join().unwrap();
    handle2.join().unwrap();
}
ログイン後にコピー

4.2. Mutex と Arc による解決

Mutex と Arc を使用して、競合状態 の問題が解決された状態でコードをコンパイルして実行することができました。

error[E0382]: use of moved value: `saldo`
ログイン後にコピー

4.3.ミューテックス vs. Rwロック

Mutex と RwLock は 競合状態 を処理するために使用され、それぞれに特有の利点があります。

Mutex: 1 つのスレッドのリソースへの排他的アクセスを保証し、解放されるまで他のスレッドへのアクセスをブロックします。これはシンプルで効果的ですが、読み取りでもリソースがブロックされるため、読み取りが多いシナリオでは効率が低下します

RwLock: .read() を使用して複数の同時読み取りを許可し、.write() を使用して排他的書き込みを制限します。 読み取り操作の並列処理が可能になることでパフォーマンスが向上するため、読み取りが優勢なシナリオに最適です


5. 結論

C と Rust の比較は、競合状態 を解決するためのさまざまなアプローチを強調しています。 C では競合状態エラーを避けるために注意が必要ですが、Rust では所有権モデルに加えて Mutex、RwLock、Arc などのツールを通じてコン​​パイル時にこれらのリスクを軽減します。これにより、コードの安全性が高まるだけでなく、サイレントバグを回避することでプログラマーの精神的負担も軽減されます

要約すると、Rust はセキュリティと信頼性を提供し、

競合 システムを開発するための優れた選択肢として自らを位置づけています。


6. 参考文献

    コード付きリポジトリ: https://github.com/z4nder/rust-data-races
  • https://en.wikipedia.org/wiki/Race_condition
  • https://blog.bughunt.com.br/o-que-sao-vulnerabilidades-race-condition/
  • https://medium.com/cwi-software/spring-boot-race-condition-e-ambiente-multi-thread-263b21e0042e
  • https://learn.microsoft.com/en-us/troubleshoot/developer/visualstudio/visual-basic/ language-compilers/race-conditions-deadlocks
  • https://www.reddit.com/r/rust/comments/18faxjg/ Understanding_threadsafety_vs_race_conditions/?rdt=52263
  • https://doc.rust-lang.org/nomicon/races.html
  • https://news.ycombinator.com/item?id=23599598

以上がRust Threads の安全性: C との比較。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:dev.to
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート