הבן את הגישה של Rust למקביליות המבוססת על המושג "מקבילות ללא פחד".
במקביל היא היכולת של תוכנית לבצע מספר משימות בו זמנית על אותה ליבת מעבד. משימות במקביל פועלות ומסתיימות בזמן חופף ללא סדר מוגדר, שלא כמו מקביליות, כאשר משימות או תת-משימות שונות של אותה משימה פועלות בו-זמנית על חומרה עם מספר מעבדים.
חלודה בולטת בתכונות הביצועים שלה ובתמיכה בו זמנית בצורה בטוחה ויעילה. הגישה של Rust למקבילות מבוססת על המושג "מקבילות ללא פחד" כאשר השפה שואפת להקל על כתיבה בטוחה קוד במקביל באמצעות מערכת הבעלות וההשאלה שלו האוכפת חוקים נוקשים בזמן הידור כדי למנוע עקבות נתונים ומבטיחה זיכרון בְּטִיחוּת.
הבנת מקיפות בחלודה
Rust מספקת מספר פרימיטיביות במקביל לכתיבת תוכניות במקביל, כולל שרשורים, העברת הודעות, מוטקסים, סוגי אטומיים ואסינכרון/המתנה לתכנות אסינכרוני.
להלן סקירה כללית של הפרימיטיבים של Rust:
- חוטים: חלודה מספקת א std:: חוט מודול בספרייה הסטנדרטית שלו ליצירה וניהול שרשורים. אתה יכול להוליד שרשורים חדשים עם thread:: השרצים פוּנקצִיָה. ה thread:: השרצים לוקח סגירה המכילה את הקוד לביצוע. אתה יכול גם להריץ שרשורים שיכולים לרוץ במקביל, ו-Rust מספק פרימיטיבים לסנכרון כדי לתאם את הביצוע שלהם. בודק ההשאלה מבטיח שהפניות לא יובילו להתנהגויות בלתי צפויות.
- הודעה עוברת: מודל המקבילות של Rust תומך בהעברת הודעות בין שרשורים. אתה תשתמש בערוצים המיושמים דרך std:: sync:: mpsc מודול להעברת הודעות. ערוץ מורכב ממשדר (שׁוֹלֵחַ) ומקלט (מַקְלֵט). חוטים יכולים לשלוח הודעות דרך המשדר ולקבל אותן דרך המקלט. זה מספק דרך בטוחה ומסונכרנת לתקשורת בין שרשורים.
- מוטקסים וסוגים אטומיים: חלודה מספקת פרימיטיבים לסנכרון, כולל מוטקסים (std:: sync:: Mutex) וסוגי אטומים (std:: sync:: אטומי), כדי להבטיח גישה בלעדית לשיתוף נתונים. Mutexes מאפשרים לשרשורים מרובים לגשת לנתונים במקביל תוך מניעת מירוצי נתונים. סוגים אטומיים מספקים פעולות אטומיות על נתונים משותפים, כגון הגדלה של מונה, מבלי לדרוש נעילה מפורשת.
- אסינכרון/חכה ועתידים: של חלודה אסינכרון/לְהַמתִין תחביר מספק פונקציונליות לכתיבת קוד אסינכרוני שניתן לבצע בו זמנית. תוכניות אסינכרוניות מתמודדות ביעילות עם משימות הקשורות ל-I/O המאפשרות לתוכניות לבצע משימות אחרות בזמן שהם ממתינים לפעולות I/O אחרות. של חלודה אסינכרון/לְהַמתִין תחביר מבוסס על חוזים עתידיים, ואתה יכול להפעיל אותם עם ה async-std אוֹ טוקיו ספריות זמן ריצה.
חוטי חלודה הם קלים, והיעדר תקורה של זמן ריצה הופך אותם למתאימים היטב ליישומים בעלי ביצועים גבוהים. הפרימיטיבים של Rust משתלבים בצורה חלקה עם ספריות ומסגרות מרובות לצורכי במקביל שונים.
כיצד להשתמש בחוטי השרצים בחלודה
אתה תשתמש ב std:: חוט מודול ליצירת שרשורים. ה std:: thread:: spawn הפונקציה מאפשרת לך ליצור שרשור חדש שיפעל במקביל לשרשור הראשי או כל שרשור קיים אחר בתוכנית שלך.
הנה איך אתה יכול להוליד שרשור עם std:: thread:: spawn פוּנקצִיָה:
להשתמש std:: thread;
fnרָאשִׁי() {
// הוליד שרשור חדש
לתת thread_handle = thread:: spawn(|| {
// הקוד שהופעל בשרשור החדש נכנס לכאן
println!("שלום מהשרשור החדש!");
});// המתן עד שהשרשור שנוצר יסתיים
thread_handle.join().unwrap();
// הקוד שבוצע בשרשור הראשי ממשיך כאן
println!("שלום מהשרשור הראשי!");
}
ה רָאשִׁי הפונקציה יוצרת שרשור חדש עם ה- thread:: השרצים פונקציה על ידי העברת סגירה המכילה את הקוד לביצוע בשרשור (במקרה זה, הסגירה היא פונקציה אנונימית). הסגירה מדפיסה הודעה המציינת שהשרשור החדש פועל.
ה לְהִצְטַרֵף שיטה על thread_handle מאפשר לשרשור הראשי להמתין עד שהשרשור שהוליד ישלים את הביצוע. על ידי התקשרות לְהִצְטַרֵף, הפונקציה מבטיחה שהשרשור הראשי ממתין להשלמת השרשור שהולידה לפני שתמשיך.
אתה יכול להוליד שרשורים מרובים ולהשתמש בלולאה או בכל לולאה אחרת מבנה בקרת חלודה כדי ליצור סגירות מרובות והשראת שרשורים לכל אחד מהם.
להשתמש std:: thread;
fnרָאשִׁי() {
לתת num_threads = 5;לתתמוט thread_handles = vec![];
ל אני ב0..num_threads {
לתת thread_handle = thread:: spawn(מהלך \ לזוז \ לעבור || {
println!("שלום מהשרשור {}", אני);
});
thread_handles.push (thread_handle);
}ל ידית ב thread_handles {
handle.join().unwrap();
}
println!("כל השרשורים הסתיימו!");
}
לולאת for מולידה חמישה שרשורים, שכל אחד מהם מוקצה למזהה ייחודי אני עם משתנה הלולאה. הסגירות תופסות את הערך של אני עם ה מהלך \ לזוז \ לעבור מילת מפתח שיש להימנע ממנה בעיות בעלות, וה ידיות_חוט וקטור מאחסן את החוטים למועד מאוחר יותר ב- לְהִצְטַרֵף לוּלָאָה.
לאחר השראת כל השרשורים, ה רָאשִׁי הפונקציה חוזרת על ה- ידיות_חוט וקטור, שיחות לְהִצְטַרֵף על כל ידית, ומחכה לביצוע כל החוטים.
העברת הודעות דרך ערוצים
אתה יכול להעביר הודעות דרך שרשורים עם ערוצים. חלודה מספקת פונקציונליות להעברת הודעות ב std:: sync:: mpsc מודול. כאן, mpsc מייצג "מפיק מרובה, צרכן יחיד" והוא מאפשר תקשורת בין שרשורים מרובים על ידי שליחת וקבלה של הודעות בערוצים.
כך אתה מיישם מסר העובר בערוצים של תקשורת בין חוטים בתוכניות שלך:
להשתמש std:: sync:: mpsc;
להשתמש std:: thread;fnרָאשִׁי() {
// צור ערוץ
לתת (שולח, מקלט) = mpsc:: channel();// הוליד שרשור
שרשור:: spawn(מהלך \ לזוז \ לעבור || {
// שלחו הודעה דרך הערוץ
sender.send("שלום מהשרשור!").לְגוֹלֵל();
});
// קבל את ההודעה בשרשור הראשי
לתת receive_message = receiver.recv().unwrap();
println!("הודעה שהתקבלה: {}", קיבל_הודעה);
}
ה רָאשִׁי הפונקציה יוצרת ערוץ עם mpsc:: channel() שמחזיר א שׁוֹלֵחַ וכן א מַקְלֵט. ה שׁוֹלֵחַ שולח הודעות ל מַקְלֵט שמקבל את ההודעות. ה רָאשִׁי הפונקציה ממשיכה להוליד שרשורים ולהעביר את הבעלות על שׁוֹלֵחַ לסגירת החוט. בתוך סגירת החוט, ה sender.send() הפונקציה שולחת הודעה דרך הערוץ.
ה receiver.recv() function מקבל את ההודעה על ידי עצירת הביצוע עד שהשרשור יקבל את ההודעה. ה רָאשִׁי הפונקציה מדפיסה את ההודעה למסוף לאחר קבלת הודעה מוצלחת.
שימו לב ששליחת הודעה דרך הערוץ צורכת את השולח. אם אתה צריך לשלוח הודעות ממספר שרשורים, אתה יכול לשכפל את השולח עם sender.clone() פוּנקצִיָה.
בנוסף, ה mpsc מודול מספק שיטות אחרות כמו try_recv(), אשר ללא חסימה מנסה לקבל הודעה, ו iter(), שיוצר איטרטור על ההודעות שהתקבלו.
העברת הודעות בערוצים מספקת דרך בטוחה ונוחה לתקשר בין שרשורים תוך הימנעות ממירוצי נתונים והבטחת סנכרון תקין.
דגם הבעלות וההשאלה של Rust מבטיח בטיחות זיכרון
Rust משלב בעלות, הלוואות ובודק ההשאלות כדי לספק מסגרת תכנות חזקה, בטוחה ובו-זמנית.
בודק ההשאלה משמש כרשת ביטחון, מזהה בעיות פוטנציאליות בזמן ההידור במקום להסתמך על בדיקות זמן ריצה או איסוף אשפה.