Foreground/Background Thread
טריד יכול להיות טריד רקע - Background והמשמעות היחידה של זה היא שכשהתהליך הראשי באפליקציה גומר הוא מפסיק אותו באמצע. לעומת זאת בטריד Foreground (וזה הברירת מחדל של טריד) האפליקציה ממתינה לסיומו.
הגדרת תהליך כBackground נעשית ע"י הצבת true למאפיין IsBackground.
Thread Priority
ניתן לתת לThread רמת עדיפות ביחס לטרידים האחרים באפליקציה שלנו (ל ביחס לתהליכים של אפליקציות אחרות במחשב. זה ניתן לשינוי אבל זה לא קשור לנושא שלנו). ע"י הצבה של ערך במאפיין Priority הערכים האפשריים הם: Lowest, BelowNormal, Normal, AboveNormal, Highest.
Thread Safety
הבעיה מס' 1 בריבוי טרידים זה מה שנקרא Thread Safety. כלומר בטיחות המידע מפני גישה של תהליכים בו זמנית.
המצב שתהליך פונה למשאב משותף ומשנה אותו בה בעת שתהליך אחר משתמש בו עשוייה להביא לתוצאות בלתי צפויות. דוגמה פשוטה: כשאנחנו עושים מונה בלולאה או בכל מקום אחר בקוד אנחנו כותבים משתנה++. המשמעות המלאה של זה היא: 1. קח את ערך המשתנה, 2. הוסף לו אחד, 3. ואכלס את ערך התוצאה במשתנה הזה (תוך דריסת הערך הקודם). עכשיו בריבוי תהליכים יכול להיות מצב שתהליך א' עושה את הפרצדורה 1 ו2, ובה בעת תהליך אחר גם כן. כעת כששניהם אוחזים בשלב 3, במקום שהמשתנה "יגדל" בשניים, הוא יגדל רק באחד. ייתכן שתהליך אחד הגדיל את המשתנה כבר בשתי פעימות, ותהליך אחר יחזיר אותו אחרוה ע"י השמת החישוב של משתנה+1 המעודכן ללפני כמה מילישניות.
הנה המחשה:
static int result = 0; //משאב משותף לשתי התהליכים
private static void Main(string[] args)
{
//יצירת שתי טרידים.
var t1 = new Thread(Do);
var t2 = new Thread(Do);
//הרצת התהליכים.
t1.Start();
t2.Start();
//הרצת המתודה גם בתהליך הראשי/נוכחי
Do();
//וידוא שהתהליכים יגמרו לפני הדפסת התוצאה
t1.Join();
t2.Join();
//הדפסת התוצאה
Console.WriteLine(result);
Console.ReadLine();
}
static void Do()
{
for (int i = 0; i < 10; i++)
{
Thread.Sleep(1); //האטת התהליך הנוכחי כדי שתהיה חפיפה בזמני הריצה.
result++;
}
}
הקוד הזה מריץ את הפונקציה Do משתי תהליכים ובנוסף מהתהליך הראשי. הפונקציה פונה שוב ושוב, 10 פעמים, למשתנה result בוחנת את ערכו ומשימה בו את הערך אות בחנה + 1. לפי החשבון המשתנה result צריך להכיל לבסוף את הערך 30, שהרי זה מס' הפעמים בהם הועלה ערכו ב1. אבל בגלל ההתנגשויות בין התהליכים הערך יהיה כל פעם משהו אחר נמוך מ30 בדרך כלל.
כמובן שהקוד הזה חסר תכלית אז קשה להציע בו שינוי מועיל.
בהודעה הבאה אציע מקרה ממחיש יותר. בו תהיה הבעיה ופתרון הLocking - בלוק קוד שרק תהליך אחד יכול להיכנס אליו בו זמנית. זה פותר את הבעיה של משתנה++. כי מתחילת התהליך עד סופו, יש רק תהליך אחד שעושה את הפעולה ברגע נתון.
רגע, מה אם JS? וNode.js? איך הם מתגוננים מכזה דבר? התשובה היא שהם עובדים על טריד אחד תמיד. האסינכרוניות שלהם עובדת על אירועים ותזמון. ממילא לעולם לא רצים במקביל שתי פקודות שעלולות לשבש או לסתור אחת את השניה. תמיד יש אחת ראשונה ואחת שניה. אכן, זה חולשה של JS בעיבוד, אבל זה לא כ"כ התפקיד שלו
פורסם במקור בפורום CODE613 ב18/05/2015 12:53 (+03:00)