JavaRush /وبلاگ جاوا /Random-FA /سطح 26. پاسخ به سؤالات مصاحبه در مورد موضوع سطح. قسمت 2. ...
zor07
مرحله
Санкт-Петербург

سطح 26. پاسخ به سؤالات مصاحبه در مورد موضوع سطح. قسمت 2. سوالات 6-9، 11-12

در گروه منتشر شد
سطح 26. پاسخ به سؤالات مصاحبه در مورد موضوع سطح.  قسمت 2. سوالات 6-9، 11-12 - 1

6. Cancarenzi چیست؟

Concurrency یک کتابخانه کلاس در جاوا است که شامل کلاس های ویژه ای است که برای کار در چندین رشته بهینه شده است. این کلاس ها در یک بسته جمع آوری می شوند java.util.concurrent. آنها را می توان به صورت شماتیک بر اساس عملکرد به شرح زیر تقسیم کرد: سطح 26. پاسخ به سؤالات مصاحبه در مورد موضوع سطح.  قسمت 2. سوالات 6-9، 11-12 - 2مجموعه های همزمان - مجموعه ای از مجموعه ها که در یک محیط چند رشته ای کارآمدتر از مجموعه های جهانی استاندارد از java.utilبسته کار می کنند. به جای یک پوشش اولیه Collections.synchronizedListبا مسدود کردن دسترسی به کل مجموعه، از قفل‌های بخش‌های داده استفاده می‌شود، یا کار برای خواندن موازی داده‌ها با استفاده از الگوریتم‌های بدون انتظار بهینه‌سازی می‌شود. صف - غیر مسدود کردن و مسدود کردن صف با پشتیبانی از چند رشته. صف های غیر مسدود کننده برای سرعت و عملکرد بدون مسدود کردن رشته ها طراحی شده اند. در صورت عدم رعایت برخی شرایط، به عنوان مثال، صف خالی یا سرریز شده یا عدم وجود «مصرف‌کننده» رایگان، از صف‌های مسدود کردن استفاده می‌شود. همگام سازها ابزارهای کمکی برای همگام سازی رشته ها هستند. آنها یک سلاح قدرتمند در محاسبات "موازی" هستند. Executors - شامل چارچوب های عالی برای ایجاد استخرهای نخ، زمان بندی وظایف ناهمزمان و به دست آوردن نتایج است. قفل - نشان دهنده مکانیسم های جایگزین و انعطاف پذیرتر همگام سازی نخ در مقایسه با موارد synchronizedپایه waitاست notify. Atomics - کلاس هایی با پشتیبانی از عملیات اتمی بر روی منابع اولیه و منابع. منبع:notifyAll

7. چه کلاس هایی از کانکارنسی را می شناسید؟

پاسخ به این سوال کاملا در این مقاله بیان شده است . من اهمیتی در چاپ مجدد همه آن در اینجا نمی بینم، بنابراین فقط در مورد کلاس هایی که افتخار آشنایی مختصر با آنها را داشتم، توضیحاتی ارائه خواهم کرد. ConcurrentHashMap<K, V> - بر خلاف Hashtableو بلوک‌های synhronizedروی HashMap، داده‌ها به شکل بخش‌هایی ارائه می‌شوند که به هش کلیدها تقسیم می‌شوند. در نتیجه، داده‌ها توسط بخش‌ها به‌جای یک شیء منفرد قابل دسترسی هستند. علاوه بر این، تکرار کننده ها داده ها را برای یک دوره زمانی خاص نشان می دهند و پرتاب نمی کنند ConcurrentModificationException. AtomicBoolean، AtomicInteger، AtomicLong، AtomicIntegerArray، AtomicLongArray - اگر در یک کلاس نیاز به همگام سازی دسترسی به یک متغیر ساده از نوع داشته باشید، چه int؟ می توانید از ساختارها با synchronizedو در هنگام استفاده از عملیات اتمی استفاده کنید set/get. volatileاما می توانید با استفاده از کلاس های جدید حتی بهتر عمل کنید Atomic*. به دلیل استفاده از CAS، عملیات با این کلاس‌ها سریع‌تر از همگام‌سازی از طریق است synchronized/volatile. به علاوه، روش‌هایی برای افزودن اتمی با مقدار معین و همچنین افزایش/کاهش وجود دارد.

8. کلاس ConcurrentHashMap چگونه کار می کند؟

تا زمان معرفی، ConcurrentHashMapتوسعه دهندگان جاوا به پیاده سازی نقشه هش زیر نیاز داشتند:
  • ایمنی نخ
  • بدون قفل در کل میز هنگام دسترسی به آن
  • مطلوب است که هنگام انجام عملیات خواندن هیچ قفل جدولی وجود نداشته باشد
ایده های اجرایی اصلی ConcurrentHashMapبه شرح زیر است:
  1. عناصر نقشه

    برخلاف عناصر HashMap، Entryin ConcurrentHashMapبه عنوان اعلان می شوند volatile. این یک ویژگی مهم است، همچنین به دلیل تغییرات در JMM .

    static final class HashEntry<K, V> {
        final K key;
        final int hash;
        volatile V value;
        final HashEntry<K, V> next;
    
        HashEntry(K key, int hash, HashEntry<K, V> next, V value) {
            this .key = key;
            this .hash = hash;
            this .next = next;
            this .value = value;
         }
    
        @SuppressWarnings("unchecked")
        static final <K, V> HashEntry<K, V>[] newArray(int i) {
            return new HashEntry[i];
        }
    }
  2. تابع هش

    ConcurrentHashMapیک عملکرد هش بهبود یافته نیز استفاده می شود.

    HashMapاجازه دهید به شما یادآوری کنم که در JDK 1.2 چگونه بود :

    static int hash(int h) {
        h ^= (h >>> 20) ^ (h >>> 12);
        return h ^ (h >>> 7) ^ (h >>> 4);
    }

    نسخه از ConcurrentHashMap JDK 1.5:

    private static int hash(int h) {
        h += (h << 15) ^ 0xffffcd7d;
        h ^= (h >>> 10);
        h += (h << 3);
        h ^= (h >>> 6);
        h += (h << 2) + (h << 14);
        return h ^ (h >>> 16);
    }

    چرا نیاز به پیچیده تر کردن تابع هش وجود دارد؟ طول جداول در نقشه هش با توان دو تعیین می شود. برای کدهای هش که نمایش های باینری آنها در موقعیت کم و بالا تفاوتی ندارند، برخورد خواهیم داشت. افزایش پیچیدگی تابع هش فقط این مشکل را حل می کند و احتمال برخورد در نقشه را کاهش می دهد.

  3. بخش ها

    نقشه به N بخش مختلف تقسیم می شود (16 به طور پیش فرض، حداکثر مقدار می تواند 16 بیت باشد و توان دو است). هر بخش یک جدول امن از عناصر نقشه است. افزایش تعداد بخش‌ها، عملیات اصلاح را تشویق می‌کند تا چندین بخش را در بر بگیرد و احتمال مسدود شدن در زمان اجرا را کاهش دهد.

  4. سطح همزمانی

    این پارامتر بر میزان استفاده از کارت حافظه و تعداد بخش های کارت تأثیر می گذارد.

    تعداد بخش‌ها به‌عنوان نزدیک‌ترین توان دو بزرگتر از ConcurrencyLevel انتخاب می‌شود. کاهش سطح همزمانی این احتمال را افزایش می دهد که رشته ها هنگام نوشتن، بخش های نقشه را مسدود کنند. برآورد بیش از حد شاخص منجر به استفاده ناکارآمد از حافظه می شود. اگر فقط یک رشته نقشه را تغییر می دهد و بقیه می خوانند، توصیه می شود از مقدار 1 استفاده کنید.

  5. جمع

    بنابراین، مزایا و ویژگی های اجرایی اصلی ConcurrentHashMap:

    • hashmapنقشه دارای یک رابط تعاملی مشابه است
    • عملیات خواندن نیازی به قفل ندارد و به صورت موازی انجام می شود
    • عملیات نوشتن اغلب می تواند به صورت موازی و بدون مسدود کردن نیز انجام شود
    • هنگام ایجاد، مورد مورد نیاز نشان داده می شود concurrencyLevelکه با خواندن و نوشتن آمار تعیین می شود
    • عناصر نقشه دارای مقداری هستند valueکه به صورت اعلام شده استvolatile
    منبع: ConcurrentHashMap چگونه کار می کند

9. کلاس Lock چیست؟

برای کنترل دسترسی به یک منبع مشترک، می توانیم از قفل ها به عنوان جایگزینی برای اپراتور همگام استفاده کنیم. عملکرد قفل در بسته بندی شده است java.util.concurrent.locks. ابتدا، موضوع سعی می کند به منبع مشترک دسترسی پیدا کند. اگر آزاد باشد، یک قفل روی نخ قرار می گیرد. پس از اتمام کار، قفل منبع مشترک آزاد می شود. اگر منبع رایگان نباشد و قفلی از قبل روی آن قرار داده شده باشد، نخ تا زمانی که این قفل آزاد شود صبر می کند. کلاس های Lock رابطی را پیاده سازی می کنند Lockکه متدهای زیر را تعریف می کند:
  • void lock():صبر می کند تا قفل بدست آید
  • boolean tryLock():سعی می کند یک قفل به دست آورد؛ اگر قفل به دست آید، true را برمی گرداند . اگر قفل به دست نیامد، false برمی‌گرداند . بر خلاف روش، lock()در صورت در دسترس نبودن قفل، منتظر نمی ماند تا قفلی به دست آورد
  • void unlock():قفل را برمی دارد
  • Condition newCondition():شیء Conditionمرتبط با قفل فعلی را برمی گرداند
سازماندهی قفل در حالت کلی بسیار ساده است: برای به دست آوردن قفل، روش نامیده می شود lock()و پس از پایان کار با منابع مشترک، روش نامیده می شود unlock()که قفل را آزاد می کند. شی Conditionبه شما امکان می دهد تا بلاک کردن را مدیریت کنید. به عنوان یک قاعده، برای کار با قفل ها، یک کلاس ReentrantLockاز بسته استفاده می شود.این java.util.concurrent.locks.کلاس رابط را پیاده سازی می کند Lock. Resourceبیایید به استفاده از Java Lock API با استفاده از یک برنامه کوچک به عنوان مثال نگاهی بیندازیم: بنابراین، فرض کنید یک کلاس با چند روش و روش ایمن برای رشته‌ای داریم که در آن ایمنی رشته مورد نیاز نیست.
public class Resource {

    public void doSomething(){
        // пусть здесь происходит работа с базой данных
    }

    public void doLogging(){
        // потокобезопасность для логгирования нам не требуется
    }
}
حالا بیایید کلاسی را انتخاب کنیم که رابط را پیاده سازی کرده Runnableو از متدهای کلاس استفاده می کند Resource.
public class SynchronizedLockExample implements Runnable{

    // экземпляр класса Resource для работы с методами
    private Resource resource;

    public SynchronizedLockExample(Resource r){
        this.resource = r;
    }

    @Override
    public void run() {
        synchronized (resource) {
            resource.doSomething();
        }
        resource.doLogging();
    }
}
حالا بیایید برنامه فوق را با استفاده از Lock API به جای synchronized.
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

// класс для работы с Lock API. Переписан с приведенной выше программы,
// но уже без использования ключевого слова synchronized
public class ConcurrencyLockExample implements Runnable{

    private Resource resource;
    private Lock lock;

    public ConcurrencyLockExample(Resource r){
        this.resource = r;
        this.lock = new ReentrantLock();
    }

    @Override
    public void run() {
        try {
            // лочим на 10 секунд
            if(lock.tryLock(10, TimeUnit.SECONDS)){
            resource.doSomething();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally{
            //убираем лок
            lock.unlock();
        }
        // Для логгирования не требуется потокобезопасность
        resource.doLogging();
    }

}
همانطور که از برنامه می بینید، ما از روشی استفاده می کنیم tryLock()تا مطمئن شویم که thread فقط برای مدت زمان مشخصی منتظر می ماند. اگر قفلی روی شیء بدست نیاورد، به سادگی وارد و خارج می شود. نکته مهم دیگر. شما باید از یک بلوک استفاده کنید try-finallyتا مطمئن شوید که قفل آزاد می شود حتی اگر روش doSomething()استثنایی ایجاد کند. منابع:

11. موتکس چیست؟

mutex یک شی خاص برای همگام سازی موضوعات/فرآیندها است. می تواند دو حالت داشته باشد - شلوغ و رایگان. برای ساده تر، mutex یک متغیر بولی است که دو مقدار اشغال (true) و free (false) را می گیرد. هنگامی که یک رشته می خواهد مالکیت انحصاری یک شی را داشته باشد، mutex خود را به عنوان مشغول علامت گذاری می کند و پس از پایان کار با آن، mutex خود را به عنوان رایگان علامت گذاری می کند. یک mutex به هر شی در جاوا متصل است. فقط ماشین جاوا دسترسی مستقیم به mutex دارد. از برنامه نویس پنهان است.

12. مانیتور چیست؟

مانیتور یک مکانیسم ویژه (یک قطعه کد) است - یک افزونه بر روی mutex که عملکرد صحیح با آن را تضمین می کند. از این گذشته، علامت گذاری که شی مشغول است کافی نیست، بلکه باید اطمینان حاصل کنیم که رشته های دیگر سعی نمی کنند از شی اشغال شده استفاده کنند. در جاوا، مانیتور با استفاده از کلمه کلیدی پیاده سازی می شود synchronized. هنگامی که یک بلوک همگام می نویسیم، کامپایلر جاوا آن را با سه قطعه کد جایگزین می کند:
  1. در ابتدای بلوک synchronized، کدی اضافه می شود که mutex را به عنوان مشغول علامت گذاری می کند.
  2. در انتهای بلوک، synchronizedیک کد اضافه می شود که mutex را به عنوان رایگان علامت گذاری می کند.
  3. قبل از بلوک، synchronizedکدی اضافه می‌شود که بررسی می‌کند آیا mutex مشغول است یا نه، سپس رشته باید منتظر باشد تا آزاد شود.
قسمت 1
نظرات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION