כיצד ליישם Multithreading ב-C++

Kyzd Lyysm Multithreading B C



ריבוי שרשורים ב-C++ הוא תכונה המאפשרת לבצע מספר משימות בו-זמנית במקביל. חוט הוא יחידת העבודה של תהליך מסוים שמתבצע. שרשורים רבים מבוצעים באופן עצמאי זה בזה בו-זמנית לביצוע ריבוי השחלות.

כיצד ליישם Multithreading ב-C++

לתוכנית ריבוי חוטים יש שני חלקים או יותר שיש להם נטייה לרוץ בו-זמנית, כל חלק ידוע בתור חוט ויש לו נתיב שונה לביצוע. שרשורים רבים מבוצעים באופן עצמאי זה בזה בו-זמנית לביצוע ריבוי השחלות.







דרישות מוקדמות לריבוי השחלות ב-C++

ב-Windows, ניתן לבצע פונקציות הקשורות לשרשורים ב-C++ 11 ובגירסאות מתקדמות. בזמן השימוש במהדר Dev-C++, כברירת מחדל הוא נמצא בגרסת C++ 3, ולכן יש לשנות אותו לגרסת C++ 11 באופן ידני. ניתן לבחור את סביבת GNU C++11 על ידי שינוי הגדרות השפה הסטנדרטיות.



פתח את המהדר Dev-C++ ועבור אל 'כלים' בשורת המשימות. בחר 'אפשרויות מהדר' ולאחר מכן בחר 'הגדרות', לחץ על בלוק 'יצירת קוד' רשימה של הפקודות תופיע. בחר GNU C++11 מתוך 'Language Standard(-std)' ולאחר מכן לחץ על אישור. כעת מהדר זה מוכן לתמוך בפעולות שרשור.




הורד את הספריות מ-GitHub ומקם אותם בתיקיית lib של מהדר Cpp. קרא לספריות אלה בתוכנית באמצעות #include 'mingw.thread.h' ו- קבצי כותרת, להלן התחביר שלה:





std::thread thread_object ( ניתן להתקשר ) ;


ה-std::thread נתמך על ידי קובץ הכותרת #include 'mingw.thread.h' ב-C++11. זה מחלקה של חוט ומייצג חוט בודד. שרשור חדש נוצר באמצעות std::thread וניתן להתקשר אליו מועבר אליו. Callable הוא קוד הפעלה, שמתבצע כאשר השרשור פועל. ניתן להתקשר יכול להיות כל אחד משלושת הסוגים המפורטים להלן:

כאשר אובייקט נוצר, הוא משיק שרשור חדש, שמבצע את הקוד ב-callable.



השקת שרשור באמצעות Function Object

אובייקט פונקציה יכול לשמש כ-calable כדי להפעיל את השרשור, אופרטור עומס יתר () הופך אותו לזמין:

class function_object_class {
מפעיל ריק ( ) ( params )
{
הצהרות;
}
}
std::thread thread_object ( class_function_object ( ) , params )


פונקציית עומס יתר מסופקת לבנאי כאובייקט הראשון והצהרות כאובייקט השני.

השקת שרשור באמצעות מצביע פונקציה

מצביע פונקציה מוגדר, ולאחר מכן הוא משמש כאמצעי להתקשרות להפעלת שרשור:

void function_call ( param )
{
הצהרות;
}
std::thread thread_obj ( function_call, params ) ;


טיעונים שיש להעביר נכתבים אחרי שם הפונקציה.

השקת שרשור באמצעות Lambda Expression

ניתן להפעיל את אובייקט ה-thread באמצעות lambda כ-Callable.

// הגדר ביטוי למבדה
אוטומטי f = [ ] ( params )
{
הצהרות;
} ;

std::thread thread_object ( f, params ) ;


ביטוי הלמבדה מוגדר, והפרמטרים נקראים בו כדי להפעיל את השרשור.

במקרים מסוימים, השרשור צריך להפסיק  לפני שהוא מתחיל לבצע את הפקודה הבאה. ה std::thread::join () הפונקציה משמשת להמתנה לסיום השרשור. לדוגמה, במקרה שאנו מקצים משימה של  GUI לשרשור, עלינו להמתין לזמן הסיום שלו כדי לטעון כראוי את ה-GUI תחילה ואז יתבצע ביצוע הפקודה הבאה.

int main ( )
{

std::thread t1 ( ניתן להתקשר ) ;
t1.join ( ) ;
הצהרות;
}

דוגמא

זוהי תוכנית המופעלת לביצוע ריבוי הליכי שרשור באמצעות כל השלושה הניתנים להתקשרות. שלושה ניתנים להתקשרות שונים מבצעים את הפקודות בהתאמה שלוש פעמים בו-זמנית מבלי להיות מופרעים זה מזה:

#include
#include
שימוש במרחב שמות std;


בטל פו ( int Z )
{
ל ( int i = 0 ; אני < ז; i++ ) {
cout << 'שרשור באמצעות פונקציה'
' מצביע כניתן להתקשרות \n ' ;
}
}


כיתה thread_obj {
פּוּמְבֵּי:
מפעיל ריק ( ) ( int x )
{
ל ( int i = 0 ; אני < איקס; i++ )
cout << 'שרשור באמצעות פונקציה'
'אובייקט וניתן להתקשרות \n ' ;
}
} ;


// קוד ראשי
int main ( )
{
cout << 'שרשורים 1 ו-2 ו-3'
'פועל באופן עצמאי'
<< endl;


חוט th1 ( פו, 3 ) ;


חוט th2 ( thread_obj ( ) , 3 ) ;


אוטומטי f = [ ] ( int x ) {
ל ( int i = 0 ; אני < איקס; i++ )
cout << 'שרשור באמצעות למבדה'
' ביטוי כניתן להתקשרות \n ' ;
} ;


חוט th3 ( ו, 3 ) ;

th1.join ( ) ;

th2.join ( ) ;

th3.join ( ) ;

לַחֲזוֹר 0 ;
}


בתוכנית זו משתמשים בשלושת האפשרויות להתקשרות כולל מצביע פונקציה, אובייקט פונקציה וביטוי למבדה כדי להפעיל את שלושת השרשורים במקביל. שרשורים 1, 2 ו-3 מדפיסים את ערכיהם במקביל, ללא תלות זה בזה, מבלי להפריע זה לזה. הם מדפיסים את הערכים שלהם שלוש פעמים. הפונקציה join() משמשת כדי לחכות לסיום השרשור.


הפלטים של כל שלושת השרשורים מוצגים באופן עצמאי וחוזרים על עצמם שלוש פעמים. כל שרשור מחכה שהשני יסתיים ראשון.

סיכום

ריבוי שרשורים ב-C++ הוא תכונה המאפשרת לבצע מספר משימות בו-זמנית במקביל. לתוכנית ריבוי חוטים יש שני מקטעים או יותר שיכולים לפעול בו זמנית, כל חלק ידוע בתור פתיל ויש לו נתיב נפרד לביצוע. ישנם שלושה שרשורים ניתנים להפעלה, מצביעי פונקציות, אובייקטי פונקציה וביטויי למבדה. אלה מאפשרים ריבוי השחלות.