JavaRush /وبلاگ جاوا /Random-FA /همگام سازی نخ اپراتور همگام سازی شده در جاوا

همگام سازی نخ اپراتور همگام سازی شده در جاوا

در گروه منتشر شد
سلام! امروز ما به بررسی ویژگی های برنامه نویسی چند رشته ای ادامه خواهیم داد و در مورد همگام سازی رشته ها صحبت خواهیم کرد.
همگام سازی نخ  اپراتور همگام شده - 1
"همگام سازی" چیست؟ خارج از قلمرو برنامه نویسی، این به نوعی تنظیمات اشاره دارد که به دو دستگاه یا برنامه اجازه می دهد با هم کار کنند. به عنوان مثال، یک تلفن هوشمند و رایانه را می توان با یک حساب Google همگام کرد، و یک حساب شخصی در یک وب سایت را می توان با حساب های موجود در شبکه های اجتماعی همگام کرد تا با استفاده از آنها وارد سیستم شوید. همگام سازی نخ ها معنای مشابهی دارد: تنظیم نحوه تعامل رشته ها با یکدیگر. در سخنرانی های قبلی، رشته های ما جدا از یکدیگر زندگی و کار می کردند. یکی داشت چیزی می شمرد، دومی خواب بود، سومی چیزی روی کنسول نمایش می داد، اما با هم تعامل نداشتند. در برنامه های واقعی چنین موقعیت هایی نادر است. چندین رشته می توانند به طور فعال، به عنوان مثال، با مجموعه ای از داده ها کار کنند و چیزی را در آن تغییر دهند. این مشکلات ایجاد می کند. تصور کنید که چندین رشته در حال نوشتن متن در یک مکان هستند، مانند یک فایل متنی یا کنسول. این فایل یا کنسول در این حالت تبدیل به یک منبع مشترک می شود. Thread ها از وجود یکدیگر اطلاعی ندارند، بنابراین آنها به سادگی هر چیزی را که می توانند مدیریت کنند در زمانی که زمانبندی رشته به آنها اختصاص می دهد، یادداشت می کنند. در یکی از سخنرانی‌های اخیر دوره، نمونه‌ای داشتیم که این منجر به چه چیزی می‌شود، بیاد داشته باشیم: همگام سازی نخ  اپراتور همگام - 2دلیل آن در این واقعیت نهفته است که رشته‌ها با یک منبع مشترک، کنسول، بدون هماهنگی اقدامات با یکدیگر کار می‌کنند. اگر زمان‌بندی رشته زمانی را به Thread-1 اختصاص داده باشد، فوراً همه چیز را در کنسول می‌نویسد. اینکه چه رشته‌های دیگری قبلاً موفق به نوشتن شده‌اند یا نتوانسته‌اند بنویسند مهم نیست. نتیجه، همانطور که می بینید، فاجعه بار است. بنابراین، در برنامه نویسی چند رشته ای، مفهوم خاصی mutex معرفی شد (از انگلیسی "mutex"، "mutual exclusion" - "mutual exclusion") . هدف از mutex ارائه مکانیزمی است که تنها یک رشته در زمان معینی به یک شی دسترسی داشته باشد. اگر Thread-1 mutex شی A را بدست آورده باشد، رشته های دیگر به آن دسترسی نخواهند داشت تا چیزی را در آن تغییر دهند. تا زمانی که mutex شی A آزاد شود، رشته های باقی مانده مجبور به صبر خواهند شد. مثال زندگی واقعی: تصور کنید که شما و 10 غریبه دیگر در یک تمرین شرکت می کنید. شما باید به نوبت نظرات خود را بیان کنید و در مورد چیزی بحث کنید. اما، از آنجایی که برای اولین بار است که یکدیگر را می بینید، برای اینکه مدام حرف یکدیگر را قطع نکنید و به هجوم نیفتید، از قانون "توپ صحبت کردن" استفاده می کنید: فقط یک نفر می تواند صحبت کند - کسی که توپ را در اختیار دارد. دست های او به این ترتیب بحث کافی و ثمربخش می شود. بنابراین، یک موتکس، در اصل، چنین توپی است. اگر mutex یک شی در دست یک رشته باشد، رشته های دیگر قادر به دسترسی به شی نخواهند بود. برای ایجاد یک mutex نیازی به انجام هیچ کاری ندارید: از قبل در کلاس تعبیه شده است Object، به این معنی که هر شی در جاوا دارای آن است.

نحوه کار اپراتور هماهنگ شده در جاوا

بیایید با یک کلمه کلیدی جدید آشنا شویم - همگام شده . این قطعه خاصی از کد ما را مشخص می کند. اگر یک بلوک کد با کلمه کلیدی همگام‌سازی شده علامت‌گذاری شود، به این معنی است که بلوک را می‌توان تنها با یک رشته در یک زمان اجرا کرد. همگام سازی را می توان به روش های مختلفی پیاده سازی کرد. به عنوان مثال، یک روش همگام کامل ایجاد کنید:
public synchronized void doSomething() {

   //...method logic
}
یا یک بلوک از کد بنویسید که در آن همگام سازی بر روی یک شی انجام می شود:
public class Main {

   private Object obj = new Object();

   public void doSomething() {

       //...some logic available to all threads

       synchronized (obj) {

           //logic that is only available to one thread at a time
       }
   }
}
معنی ساده است. اگر یک رشته وارد بلوک کدی شود که با کلمه synchronized علامت گذاری شده است، فورا mutex شی را بدست می آورد و همه رشته های دیگری که سعی می کنند وارد همان بلوک یا روش شوند، مجبور می شوند منتظر بمانند تا رشته قبلی کار خود را کامل کند و آزاد شود. نظارت کنید. همگام سازی نخ  اپراتور همگام - 3راستی! در سخنرانی‌های دوره قبلاً نمونه‌هایی از همگام‌سازی شده را دیده‌اید، اما آنها متفاوت به نظر می‌رسند:
public void swap()
{
   synchronized (this)
   {
       //...method logic
   }
}
مبحث برای شما جدید است و البته در ابتدا با سینتکس اشتباه می شود. بنابراین، فوراً به خاطر بسپارید تا بعداً در روش های نوشتن گیج نشوید. این دو روش نوشتن به یک معنا هستند:
public void swap() {

   synchronized (this)
   {
       //...method logic
   }
}


public synchronized void swap() {

   }
}
در حالت اول، بلافاصله پس از ورود به روش، یک بلوک همگام سازی شده از کد ایجاد می کنید. thisبا شیء ، یعنی با شی فعلی همگام می شود . و در مثال دوم کلمه synchronized را روی کل متد قرار دادید. دیگر نیازی به نشان دادن صریح هیچ شیئی که همگام سازی روی آن انجام می شود وجود ندارد. هنگامی که کل یک متد با یک کلمه علامت گذاری می شود، این متد به طور خودکار برای تمام اشیاء کلاس همگام می شود. بیایید به این بحث نپردازیم که کدام روش بهتر است. در حال حاضر، آنچه را که بیشتر دوست دارید انتخاب کنید :) نکته اصلی این است که به خاطر بسپارید: فقط زمانی می توانید یک روش را همزمان اعلام کنید که تمام منطق داخل آن توسط یک رشته به طور همزمان اجرا شود. به عنوان مثال، در این مورد، doSomething()همگام سازی متد با خطا همراه خواهد بود:
public class Main {

   private Object obj = new Object();

   public void doSomething() {

       //...some logic available to all threads

       synchronized (obj) {

           //logic that is only available to one thread at a time
       }
   }
}
همانطور که می بینید، یک قطعه از روش حاوی منطق است که برای آن نیازی به همگام سازی نیست. کد موجود در آن می تواند توسط چندین رشته به طور همزمان اجرا شود و تمام مکان های بحرانی به یک بلوک همگام جداگانه اختصاص داده می شود. و یک لحظه بیایید زیر میکروسکوپ به مثال خود از سخنرانی با تبادل نام نگاه کنیم:
public void swap()
{
   synchronized (this)
   {
       //...method logic
   }
}
لطفا توجه داشته باشید: همگام سازی با استفاده از this. یعنی برای یک شی خاص MyClass. تصور کنید که ما 2 رشته ( Thread-1و Thread-2) و فقط یک شی داریم MyClass myClass. در این حالت، اگر Thread-1متد فراخوانی شود myClass.swap()، mutex شی مشغول خواهد بود و Thread-2زمانی که می خواهید آن را فراخوانی کنید، myClass.swap()منتظر آزاد شدن mutex خواهد ماند. اگر 2 رشته و 2 شی MyClass- myClass1و myClass2- روی آبجکت های مختلف داشته باشیم، رشته های ما به راحتی می توانند به طور همزمان متدهای همگام سازی شده را اجرا کنند. تاپیک اول انجام می دهد:
myClass1.swap();
دومی انجام می دهد:
myClass2.swap();
در این مورد، کلمه کلیدی همگام سازی شده در داخل روش swap()بر عملکرد برنامه تأثیر نمی گذارد، زیرا همگام سازی روی یک شی خاص انجام می شود. و در حالت دوم 2 شی داریم.بنابراین نخ ها برای هم مشکلی ایجاد نمی کنند. از این گذشته ، دو شیء دارای 2 mutexe مختلف هستند و گرفتن آنها به یکدیگر بستگی ندارد.

ویژگی های همگام سازی در روش های ایستا

اما اگر نیاز به همگام سازی یک روش استاتیک داشته باشید، چه؟
class MyClass {
   private static String name1 = "Olya";
   private static String name2 = "Lena";

   public static synchronized void swap() {
       String s = name1;
       name1 = name2;
       name2 = s;
   }

}
مشخص نیست که در این مورد چه چیزی به عنوان mutex عمل می کند. از این گذشته، ما قبلاً تصمیم گرفته ایم که هر شی یک mutex دارد. اما مشکل اینجاست که برای فراخوانی یک متد استاتیک MyClass.swap()به اشیا نیازی نداریم: متد ثابت است! بنابراین، بعدی چیست؟ :/ در واقع این هیچ مشکلی ندارد. سازندگان جاوا مراقب همه چیز بودند :) اگر متدی که حاوی منطق بحرانی "چند رشته ای" است ایستا باشد، همگام سازی توسط کلاس انجام می شود. برای وضوح بیشتر، کد بالا را می توان به صورت زیر بازنویسی کرد:
class MyClass {
   private static String name1 = "Olya";
   private static String name2 = "Lena";

   public static void swap() {

       synchronized (MyClass.class) {
           String s = name1;
           name1 = name2;
           name2 = s;
       }
   }

}
در اصل، شما می توانستید به تنهایی به این فکر کنید: از آنجایی که هیچ اشیایی وجود ندارد، مکانیسم همگام سازی باید به نحوی در خود کلاس ها "هارد" شود. این طور است: شما همچنین می توانید در کلاس ها همگام سازی کنید.
نظرات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION