CodeGym /وبلاگ جاوا /Random-FA /همگام سازی نخ اپراتور هماهنگ شده
John Squirrels
مرحله
San Francisco

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

در گروه منتشر شد
سلام! امروز ما به بررسی ویژگی های برنامه نویسی چند رشته ای و صحبت در مورد همگام سازی رشته ها ادامه خواهیم داد. همگام سازی نخ  اپراتور هماهنگ شده - 1

همگام سازی در جاوا چیست؟

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

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

بیایید با یک کلمه کلیدی جدید آشنا شویم: همگام . برای علامت گذاری یک بلوک خاص از کد استفاده می شود. اگر یک بلوک کد با synchronizedکلمه کلیدی مشخص شده باشد، آن بلوک فقط می تواند توسط یک رشته در یک زمان اجرا شود. همگام سازی را می توان به روش های مختلفی پیاده سازی کرد. به عنوان مثال، با اعلام یک متد کامل برای همگام سازی:

public synchronized void doSomething() {

   // ...Method logic
}
یا یک بلوک کد بنویسید که در آن همگام سازی با استفاده از یک شی انجام می شود:

public class Main {

   private Object obj = new Object();

   public void doSomething() {

       // ...Some logic available simultaneously to all threads

       synchronized (obj) {

           // Logic available to just one thread at a time
       }
   }
}
معنی ساده است. اگر یک رشته به داخل بلوک کد مشخص شده با synchronizedکلمه کلیدی وارد شود، فورا mutex شی را می گیرد و تمام رشته های دیگر که سعی می کنند وارد همان بلوک یا روش شوند، مجبور می شوند منتظر بمانند تا رشته قبلی کار خود را کامل کند و مانیتور را آزاد کند. همگام سازی نخ  اپراتور هماهنگ شده - 3راستی! در طول دوره، شما قبلاً نمونه هایی از را دیده اید synchronized، اما آنها متفاوت به نظر می رسیدند:

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 simultaneously to all threads

       synchronized (obj) {

           // Logic available to just one thread at a time
       }
   }
}
همانطور که می بینید، بخشی از متد حاوی منطق است که نیازی به همگام سازی ندارد. این کد می تواند توسط چندین رشته به طور همزمان اجرا شود و همه مکان های مهم در یک synchronizedبلوک جداگانه از هم جدا می شوند. و یه چیز دیگه بیایید مثال خود را از درس با تعویض نام به دقت بررسی کنیم:

public void swap()
{
   synchronized (this)
   {
       // ...Method logic
   }
}
توجه: همگام سازی با استفاده ازthis. یعنی استفاده از یکMyClassشی خاص. Thread-1فرض کنید 2 رشته ( وThread-2) و فقط یکMyClass myClassشیداریمدر این حالت، اگرThread-1را فراخوانی کندmyClass.swap()، mutex شی مشغول خواهد بود و در هنگام تلاش برای فراخوانی متدmyClass.swap()درThread-2حالی که منتظر آزاد شدن mutex است، هنگ می کند. MyClassاگر 2 رشته و 2 شی (myClass1وداشته باشیمmyClass2، رشته های ما به راحتی می توانند به طور همزمان متدهای همگام سازی شده را روی اشیاء مختلف اجرا کنند. نخ اول این را اجرا می کند:

myClass1.swap();
دومی این را اجرا می کند:

myClass2.swap();
در این حالت، synchronizedکلمه کلیدی داخل swap()متد بر عملکرد برنامه تاثیری نخواهد داشت، زیرا همگام سازی با استفاده از یک شی خاص انجام می شود. و در مورد دوم 2 شی داریم. بنابراین، نخ ها برای یکدیگر مشکلی ایجاد نمی کنند. به هر حال، دو شی دارای 2 mutexe مختلف هستند و به دست آوردن یکی مستقل از به دست آوردن دیگری است .

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

اما اگر نیاز به همگام سازی یک روش استاتیک داشته باشید، چه ؟

class MyClass {
   private static String name1 = "Ally";
   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 = "Ally";
   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