0Pricing
Learn Rust Coding · درس

المشاركة باستخدام Arc وMutex

عدّل الحالة المشتركة بأمان

المشاركة باستخدام Arc وMutex درس مجاني في Learn Rust Coding على CoddyKit. هذا هو الدرس 3 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Learn Rust Coding، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Learn Rust Coding 4 دروس في المجموع.

الحاجة إلى الحالة المشتركة

تحتاج عدة خيوط أحيانًا إلى قراءة البيانات نفسها أو تحديثها. ولا يكفي نقل الملكية إلى خيط واحد.

يوفر Rust ملكية مشتركة آمنة عبر الخيوط باستخدام Arc، وتعديلًا آمنًا باستخدام Mutex. وتمكّنهما معًا من إنشاء حالة مشتركة قابلة للتعديل.

Arc: عدّ المراجع الذري

يرمز Arc إلى عدّ المراجع الذري. وهو يشبه Rc، لكن عدّاده يستخدم عمليات ذرية، ولذلك يكون آمنًا عبر الخيوط.

لا يؤدي استنساخ Arc إلى نسخ البيانات، بل يزيد العدد فقط ويعيد مقبضًا آخر للقيمة نفسها.

use std::sync::Arc;

fn main() {
    let shared = Arc::new(vec![1, 2, 3]);
    let clone = Arc::clone(&shared);
    println!("{:?} {:?}", shared, clone);
}

مشاركة Arc بين الخيوط

لمشاركة بيانات للقراءة فقط، استنسخوا Arc مرة لكل خيط وانقلوا كل نسخة إلى خيطها. وتشير جميع الخيوط إلى التخصيص نفسه.

وبما أن Arc يطبّق Send وSync، فستتم ترجمة ذلك بسلاسة.

use std::sync::Arc;
use std::thread;

fn main() {
    let data = Arc::new(vec![10, 20, 30]);
    let mut handles = vec![];
    for i in 0..3 {
        let d = Arc::clone(&data);
        handles.push(thread::spawn(move || println!("{}", d[i])));
    }
    for h in handles { h.join().unwrap(); }
}

Arc وحده للقراءة فقط

يوفر Arc ملكية مشتركة، لكنه لا يتيح سوى وصول مشترك وغير قابل للتعديل إلى القيمة الداخلية.

لا يمكنكم تعديل البيانات مباشرةً عبر Arc، لأن امتلاك عدة خيوط له في الوقت نفسه قد يؤدي إلى تعارض. وتحتاجون إلى قابلية تعديل داخلية باستخدام قفل.

Mutex: الاستبعاد المتبادل

يحمي Mutex البيانات بحيث لا يتمكن سوى خيط واحد من الوصول إليها في كل مرة. وتستدعون lock للحصول على الوصول.

يعيد lock قيمة من النوع Result؛ ويمنح فك التغليف حارسًا على شكل مؤشر ذكي. وتحظر الخيوط الأخرى حتى إسقاط الحارس.

use std::sync::Mutex;

fn main() {
    let m = Mutex::new(0);
    {
        let mut guard = m.lock().unwrap();
        *guard += 5;
    }
    println!("{:?}", m);
}

الحارس وRAII

تُسمى القيمة التي يعيدها lock باسم MutexGuard. ويمكنكم الوصول إلى البيانات الداخلية من خلال إلغاء الإشارة إليها باستخدام *.

عندما يخرج الحارس من النطاق، يُحرَّر القفل تلقائيًا. ويمنع أسلوب RAII هذا نسيان إلغاء القفل.

دمج Arc وMutex

لمشاركة حالة قابلة للتعديل بين الخيوط، غلّفوا Mutex داخل Arc. يشارك Arc الملكية، بينما يحمي Mutex التعديل.

يُعد هذا النمط، Arc<Mutex<T>>، الطريقة القياسية لإنشاء حالة مشتركة قابلة للتعديل في Rust.

use std::sync::{Arc, Mutex};

fn main() {
    let counter = Arc::new(Mutex::new(0));
    let c = Arc::clone(&counter);
    *c.lock().unwrap() += 1;
    println!("{}", *counter.lock().unwrap());
}

عداد مشترك

تزيد هنا عشرة خيوط عدادًا مشتركًا، إذ يستنسخ كل منها Arc، ويقفل Mutex، ثم يضيف واحدًا.

وبما أن القفل ينظّم الوصول بالتتابع، فإن المجموع النهائي يكون دائمًا عشرة بالضبط.

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 c = Arc::clone(&counter);
        handles.push(thread::spawn(move || {
            *c.lock().unwrap() += 1;
        }));
    }
    for h in handles { h.join().unwrap(); }
    println!("{}", *counter.lock().unwrap());
}

أبقوا الأقسام الحرجة قصيرة

يُسمى الكود الذي يُنفذ أثناء الاحتفاظ بالقفل القسم الحرج. وتنتظر الخيوط الأخرى عنده، لذلك احرصوا على إبقائه قصيرًا.

اقفلوا، ونفّذوا التحديث الضروري فقط، ثم حرّروا القفل. وتجنبوا العمليات الحسابية المكثفة أو عمليات الإدخال والإخراج أثناء الاحتفاظ بالقفل.

use std::sync::Mutex;

fn main() {
    let m = Mutex::new(Vec::new());
    {
        let mut v = m.lock().unwrap();
        v.push(1);
    } // lock released here
    println!("{:?}", m.lock().unwrap());
}

حالات الجمود وتسمم الأقفال

إذا قفل خيط واحد Mutex نفسه مرتين، أو قفل خيطان قفلين بترتيبين متعاكسين، فقد تحدث حالة جمود ويتوقف التنفيذ إلى الأبد.

إذا حدثت panic في خيط أثناء احتفاظه بقفل، يصبح Mutex مسمومًا، وتعيد استدعاءات lock اللاحقة قيمة Err.

RwLock لعدة قرّاء

عندما يفوق عدد عمليات القراءة عدد عمليات الكتابة بكثير، قد يكون RwLock أفضل من Mutex. فهو يتيح لعدة قرّاء الوصول بالتزامن أو لكاتب واحد الوصول بشكل حصري.

استخدموا read للوصول المشترك وwrite للوصول الحصري.

use std::sync::RwLock;

fn main() {
    let lock = RwLock::new(5);
    {
        let r = lock.read().unwrap();
        println!("read {}", *r);
    }
    *lock.write().unwrap() += 1;
    println!("{}", *lock.read().unwrap());
}

تحقق سريع

اختبروا مدى فهمكم لـ Arc وMutex.

مراجعة

تعلّمتم أن Arc يشارك الملكية بين الخيوط باستخدام عدّ المراجع الذري، لكنه لا يتيح سوى الوصول غير القابل للتعديل.

يحمي Mutex التعديل، ويوفر حارسًا يُحرّر القفل عند إسقاطه. ادمجوهما بالشكل Arc<Mutex<T>> لإنشاء حالة مشتركة قابلة للتعديل، مع الانتباه إلى حالات الجمود وتسمم الأقفال.

سترون بعد ذلك كيفية ضم الخيوط وتجميع نتائجها.

الأسئلة الشائعة

هل درس «المشاركة باستخدام Arc وMutex» مجاني؟

نعم — نص درس «المشاركة باستخدام Arc وMutex» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Learn Rust Coding، انتقل إلى CoddyKit PRO. تتضمن دورة Learn Rust Coding 4 دروس في المجموع.

ماذا ستتعلم في «المشاركة باستخدام Arc وMutex»؟

عدّل الحالة المشتركة بأمان تتمرن على Learn Rust Coding مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ Learn Rust Coding؟

لا تُشترط خبرة سابقة. Learn Rust Coding على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 3 من أصل 4.

كم من الوقت يستغرق درس «المشاركة باستخدام Arc وMutex»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس Learn Rust Coding هذا؟

نعم. كل درس في Learn Rust Coding يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. إنشاء الخيوط
  2. نقل البيانات إلى الخيوط
  3. المشاركة باستخدام Arc وMutex
  4. ضمّ الخيوط وتجميع النتائج
← العودة إلى Learn Rust Coding