מתי להשתמש במילת המפתח ההפכפכה ב- C #

טכניקות האופטימיזציה בהן משתמש מהדר ה- JIT (בדיוק בזמן) ב- Runtime Common Language עשויה להוביל לתוצאות בלתי צפויות כאשר תוכנית ה- NET שלך מנסה לבצע קריאות לא נדיפות של נתונים בתרחיש רב-הברגה. במאמר זה נבחן את ההבדלים בין גישה לזיכרון נדיף ולא נדיף, תפקידה של מילת המפתח ההפכפכה ב- C # וכיצד יש להשתמש במילת המפתח ההפכפכה.

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

הבנת אופטימיזציות של מהדר JIT

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

x = 0;

x = 1;

ניתן לשנות את קטע הקוד לעיל - תוך שמירה על הסמנטיקה המקורית של התוכנית.

x = 1;

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

x = 1;

y = x;

ניתן לשנות את קטע הקוד לעיל להבא - שוב תוך שמירה על הסמנטיקה המקורית של התוכנית.

x = 1;

y = 1;

גישה לזיכרון נדיף לעומת לא נדיף

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

כאשר שרשור אחד מקיים אינטראקציה עם הנתונים במטמון, ושרשור שני מנסה לקרוא את אותם נתונים במקביל, השרשור השני עשוי לקרוא גרסה מיושנת של הנתונים מהזיכרון הראשי. הסיבה לכך היא שכאשר הערך של אובייקט שאינו נדיף מתעדכן, השינוי נעשה במטמון של השרשור המבצע ולא בזיכרון הראשי. עם זאת, כאשר הערך של אובייקט נדיף מתעדכן, לא רק שהשינוי נעשה במטמון של השרשור המבצע, אלא שמטמון זה נשטף לזיכרון הראשי. וכאשר קוראים את הערך של אובייקט נדיף, השרשור מרענן את המטמון וקורא את הערך המעודכן.

שימוש במילת המפתח הפכפכה ב- C #

מילת המפתח הפכפכה ב- C # משמשת כדי להודיע ​​למהדר JIT כי לעולם אין לשמור את ערך המשתנה משום שהוא עשוי להשתנות על ידי מערכת ההפעלה, החומרה או שרשור ההפעלה בו זמנית. המהדר נמנע אפוא משימוש בכל אופטימיזציות על המשתנה העלולות להוביל להתנגשויות נתונים, כלומר לשרשורים שונים הגישה לערכים שונים של המשתנה.

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

ניתן להכריז על משתנה כהפכפך על ידי הקדמתו עם volatileמילת המפתח. קטע הקוד הבא ממחיש זאת.

תכנית כיתתית

    {

        תנודתיות ציבורית i;

        ריק סטטי ראשי (מחרוזת [] טענות)

        {

            // כתוב כאן את הקוד שלך

        }

    }

אתה יכול להשתמש volatileבמילת המפתח עם כל סוג הפניה, מצביע וסוג enum. אתה יכול גם להשתמש בשינוי הנדיף עם סוגי בתים, קצר, int, char, float ו- bool. יש לציין כי לא ניתן להכריז על משתנים מקומיים כנדיפים. כאשר אתה מציין אובייקט מסוג הפניה כנדיף, רק המצביע (מספר שלם של 32 סיביות שמצביע על המיקום בזיכרון שבו האחסון מאוחסן בפועל) הוא נדיף, ולא הערך של המופע. כמו כן, משתנה כפול אינו יכול להיות נדיף מכיוון שהוא בגודל 64 סיביות, גדול יותר מגודל המילה במערכות x86. אם אתה צריך לעשות משתנה כפול נדיף, עליך לעטוף אותו בכיתה. אתה יכול לעשות זאת בקלות על ידי יצירת מחלקת עטיפה כפי שמוצג בקטע הקוד שלמטה.

מעמד ציבורי VolatileDoubleDemo

{

    פרטי נדיף WrappedVolatileDouble נדיף נתונים;

}

כיתה ציבורית WrappedVolatileDouble

{

    נתונים כפולים ציבוריים {get; מַעֲרֶכֶת; }

עם זאת, שים לב למגבלה של דוגמת הקוד לעיל. למרות שהיה לך הערך האחרון של volatileDataמצביע הייחוס, לא מובטח לך שהערך האחרון של Dataהנכס. העבודה סביב זה היא להפוך את WrappedVolatileDoubleהסוג לבלתי משתנה.

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