סנכרון בג'אווה: מה, איך ולמה?



מאמר זה על סנכרון ב- Java יעזור לכם להנחות את דרכם ללמוד על סנכרון בין תוכניות מרובות הליכי משנה.

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

אדון בנושאים בסדר זה:





בואו נתחיל!

מדוע להשתמש בסינכרון ב- Java?



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

תחביר :

מסונכרן (objectidentifier) ​​{// גישה למשתנים משותפים ומשאבים משותפים אחרים}

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



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

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

סוגי סנכרון

יש בעצם שני סוגים של סנכרון. הם:

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

בואו לא ניכנס לפרטים מהסוגים הללו וננסה להבין מה הם נעולים .

מנעולים בג'אווה

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

מ- Java 5, החבילה java.util.concurrent.locks מכילה יישומי נעילה רבים.

כך נראה מנעול:

מעמד ציבורי מנעול {פרטי בוליאני isLocked = מנעול ריק מסונכרן ציבורי כוזב () זורק InterruptedException {בזמן (isLocked) {המתן ()} isLocked = נכון} ביטול ביטול נעילה ריק מסונכרן () {isLocked = false הודעה ()}}

שיטת הנעילה () נועלת את מופע הנעילה כך שכל החוטים הקוראים לנעילה () נחסמים עד לביטול הנעילה ().

השחלה מרובה ללא סנכרון

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

class Multithread {public void printCount () {try {for (int i = 5 i<0 i--) { System.out.println('Counter --- ' + i ) } } catch (Exception e) { System.out.println('Thread interrupted.') } } } class Thread extends Multithread { private Thread t private String threadName Multithread MT Thread( String name, Multithread mt) { threadName = name MT= mt } public void run() { MT.printCount() System.out.println('Thread ' + threadName + ' exiting.') } public void start () { System.out.println('Starting ' + threadName ) if (t == null) { t = new Thread (this, threadName) t.start () } } } public class TestThread { public static void main(String args[]) { Multithread MT = new Multithread() Thread t = new Thread( 'Thread - 1 ', MT) Thread t1 = new Thread( 'Thread - 2 ', MT) t.start() t1.start() // wait for threads to end try { t.join() t1.join() } catch ( Exception e) { System.out.println('Interrupted') } } }

תוצאות התוכנית שלעיל בעניין זה:

כיצד להפסיק תוכנית Java בקוד

פלט- סנכרון בג

השחלה מרובה עם סנכרון

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

class Multithread {public void printCount () {try {for (int i = 5 i> 0 i--) {System.out.println ('Counter ---' + i)}} לתפוס (חריג e) {System. out.println ('החוט הופרע.')}}} class Thread מרחיב Multithread {private Thread t private String threadName Multithread MT Thread (שם מחרוזת, Multithread mt) {threadName = name MT = mt} הפעלה בטלנית ציבורית () {מסונכרן ( MT) {MT.printCount ()} System.out.println ('חוט' + threadName + 'יוצא.')} התחל ריק ריק () {System.out.println ('הפעלה' + threadName) אם (t == null) {t = אשכול חדש (זה, threadName) t.start ()}}} מחלקה ציבורית TestThread {public static void main (String args []) {Multithread MT = new Multithread () Thread T = thread new ('Thread - 1 ', MT) חוט T1 = חוט חדש (' Thread - 2 ', MT) T. start () T1.start () // המתן לסיום השרשורים נסה {T.join () T1.join ()} לתפוס (חריג e) {System.out.println ('מופרע')}}}

הפלט מתואר להלן:

מילת מפתח מסונכרנת

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

ניתן להשתמש במילת המפתח המסונכרנת עם:

כיצד להקצות באופן דינמי מערך ב - Java

בואו נדון בבלוק הקוד.

מילת מפתח מסונכרנת: בלוק קוד

תחביר

התחביר הכללי לכתיבת גוש מסונכרן הוא:

מסונכרן (lockObject) {// הצהרות מסונכרנות}

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

הערה :

  • אם חוט מושקע בשינה (באמצעות לִישׁוֹן() שיטה) אז זה לא משחרר את הנעילה. בזמן שינה זה, שום שרשור לא יבצע את הצהרות החסימה המסונכרנות.
  • סינכרון Java ייזרק NullPointerException אם נעשה שימוש בחפץ נעילה מסונכרן (נעילה) 'הוא אפס.

עכשיו, בואו נדון בשיטה.

מילת מפתח מסונכרנת: שיטה

תחביר

התחביר הכללי לכתיבת א שיטה מסונכרנת הוא:

שיטה מסונכרנת (פרמטרים) {// קוד מסונכרן}

כאן lockObject הוא רק התייחסות לאובייקט שהמנעול שלו משויך לצג שמייצג את ההצהרות המסונכרנות.

בדומה לבלוק המסונכרן, חוט חייב לרכוש את הנעילה על אובייקט המוניטור המחובר בשיטה המסונכרנת. במקרה של שיטה מסונכרנת, אובייקט הנעילה הוא:

  • אובייקט '.class' - אם השיטה הנתונה היא סטָטִי .
  • אובייקט 'זה' - אם השיטה היא לא סטטי . 'זה' הוא ההתייחסות לאובייקט הנוכחי בו מופעלת השיטה המסונכרנת.

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

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

ההבדל בין מילת מפתח מסונכרנת לחסימה מסונכרנת

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

זה מביא אותנו לסוף מאמר זה בו דנו כיצד בדיוק הסינכרון ב- Java עובד. מקווה שברור לך עם כל מה ששותף איתך במדריך זה.

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

יש לך שאלה עבורנו? אנא הזכיר זאת בסעיף ההערות של סנכרון זה ב- Java ' מאמר ונחזור אליך בהקדם האפשרי.