JavaRush /Blog Java /Random-MS /Aras 26. Jawapan kepada soalan temu bual mengenai topik a...
zor07
Tahap
Санкт-Петербург

Aras 26. Jawapan kepada soalan temu bual mengenai topik aras. Bahagian 2. Soalan 6-9, 11-12

Diterbitkan dalam kumpulan
Aras 26. Jawapan kepada soalan temu bual mengenai topik aras.  Bahagian 2. Soalan 6-9, 11-12 - 1

6. Apakah itu Cancarenzi?

Concurrency ialah perpustakaan kelas dalam Java yang mengandungi kelas khas yang dioptimumkan untuk bekerja merentas berbilang rangkaian. Kelas-kelas ini dikumpulkan dalam satu pakej java.util.concurrent. Mereka boleh dibahagikan secara skematik mengikut fungsi seperti berikut: Aras 26. Jawapan kepada soalan temu bual mengenai topik aras.  Bahagian 2. Soalan 6-9, 11-12 - 2Koleksi Serentak - satu set koleksi yang berfungsi dengan lebih cekap dalam persekitaran berbilang benang daripada koleksi universal standard daripada java.utilpakej. Daripada pembungkus asas Collections.synchronizedListdengan menyekat akses kepada keseluruhan koleksi, kunci pada segmen data digunakan atau kerja dioptimumkan untuk bacaan selari data menggunakan algoritma tanpa menunggu. Baris gilir - tidak menyekat dan menyekat baris gilir dengan sokongan berbilang benang. Baris gilir tanpa sekatan direka untuk kelajuan dan operasi tanpa menyekat benang. Barisan gilir menyekat digunakan apabila anda perlu "memperlahankan" urutan "Pengeluar" atau "Pengguna" jika beberapa syarat tidak dipenuhi, contohnya, baris gilir kosong atau melimpah, atau tiada "Pengguna" percuma. Penyegerak ialah utiliti tambahan untuk menyegerakkan benang. Mereka adalah senjata yang kuat dalam pengkomputeran "selari". Pelaksana - mengandungi rangka kerja yang sangat baik untuk mencipta kumpulan benang, menjadualkan tugas tak segerak dan mendapatkan hasil. Kunci - mewakili mekanisme penyegerakan benang alternatif dan lebih fleksibel berbanding dengan synchronizedmekanisme waitasas notify. Atomics - kelas dengan sokongan untuk operasi atom pada primitif dan rujukan. Sumber:notifyAll

7. Apakah kelas dari Kankarensi yang anda tahu?

Jawapan kepada soalan ini dinyatakan dengan sempurna dalam artikel ini . Saya tidak nampak gunanya mencetak semula semuanya di sini, jadi saya hanya akan memberikan penerangan tentang kelas-kelas yang saya mendapat penghormatan untuk membiasakan diri secara ringkas. ConcurrentHashMap<K, V> - Tidak seperti Hashtabledan sekat synhronizedpada HashMap, data dibentangkan dalam bentuk segmen, dibahagikan kepada cincangan kunci. Akibatnya, data diakses oleh segmen dan bukannya oleh objek tunggal. Selain itu, iterator mewakili data untuk tempoh masa tertentu dan tidak membuang ConcurrentModificationException. AtomicBoolean, AtomicInteger, AtomicLong, AtomicIntegerArray, AtomicLongArray - Bagaimana jika dalam kelas anda perlu menyegerakkan akses kepada satu pembolehubah mudah jenis int? Anda boleh menggunakan binaan dengan synchronized, dan apabila menggunakan operasi atom set/get, volatile. Tetapi anda boleh melakukan yang lebih baik dengan menggunakan kelas baharu Atomic*. Disebabkan penggunaan CAS, operasi dengan kelas ini lebih pantas berbanding jika disegerakkan melalui synchronized/volatile. Selain itu, terdapat kaedah untuk penambahan atom mengikut jumlah tertentu, serta kenaikan/penurunan.

8. Bagaimanakah kelas ConcurrentHashMap berfungsi?

Pada masa pengenalannya, ConcurrentHashMappembangun Java memerlukan pelaksanaan peta cincang berikut:
  • Keselamatan benang
  • Tiada kunci pada keseluruhan meja semasa mengaksesnya
  • Adalah wajar bahawa tiada kunci meja semasa melakukan operasi baca
Idea pelaksanaan utama ConcurrentHashMapadalah seperti berikut:
  1. Unsur peta

    Tidak seperti unsur HashMap, Entrydalam ConcurrentHashMapdiisytiharkan sebagai volatile. Ini adalah ciri penting, juga disebabkan oleh perubahan dalam 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. Fungsi hash

    ConcurrentHashMapfungsi pencincangan yang dipertingkatkan juga digunakan.

    Biar saya ingatkan anda bagaimana keadaannya dalam HashMapJDK 1.2:

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

    Versi daripada 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);
    }

    Mengapakah terdapat keperluan untuk menjadikan fungsi hash lebih kompleks? Jadual dalam peta cincang mempunyai panjang yang ditentukan oleh kuasa dua. Untuk kod cincang yang perwakilan binarinya tidak berbeza dalam kedudukan rendah dan tinggi, kami akan mengalami perlanggaran. Meningkatkan kerumitan fungsi cincang hanya menyelesaikan masalah ini, mengurangkan kemungkinan perlanggaran dalam peta.

  3. Segmen

    Peta dibahagikan kepada N segmen berbeza (16 secara lalai, nilai maksimum boleh menjadi 16 bit dan merupakan kuasa dua). Setiap segmen ialah jadual elemen peta selamat benang. Menambah bilangan segmen akan menggalakkan operasi pengubahsuaian untuk menjangkau berbilang segmen, mengurangkan kemungkinan menyekat pada masa jalan.

  4. ConcurrencyLevel

    Parameter ini mempengaruhi penggunaan kad memori dan bilangan segmen dalam kad.

    Bilangan segmen akan dipilih sebagai kuasa terdekat dua lebih besar daripada concurrencyLevel. Menurunkan concurrencyLevel menjadikannya lebih berkemungkinan bahawa urutan akan menyekat segmen peta semasa menulis. Anggaran berlebihan penunjuk membawa kepada penggunaan memori yang tidak cekap. Jika hanya satu utas yang akan mengubah suai peta, dan selebihnya akan dibaca, adalah disyorkan untuk menggunakan nilai 1.

  5. Jumlah

    Jadi, kelebihan utama dan ciri pelaksanaan ConcurrentHashMap:

    • hashmapPeta mempunyai antara muka interaksi yang serupa dengan
    • Operasi baca tidak memerlukan kunci dan dilakukan secara selari
    • Operasi tulis selalunya juga boleh dilakukan secara selari tanpa menyekat
    • Semasa membuat, yang diperlukan ditunjukkan concurrencyLevel, ditentukan dengan membaca dan menulis statistik
    • Unsur peta mempunyai nilai valueyang diisytiharkan sebagaivolatile
    Sumber: Cara ConcurrentHashMap Berfungsi

9. Apakah kelas Lock?

Untuk mengawal akses kepada sumber yang dikongsi, kami boleh menggunakan kunci sebagai alternatif kepada pengendali yang disegerakkan. Fungsi penguncian dibungkus dalam java.util.concurrent.locks. Pertama, urutan cuba mengakses sumber yang dikongsi. Sekiranya ia percuma, maka kunci diletakkan pada benang. Setelah kerja selesai, kunci pada sumber yang dikongsi dilepaskan. Jika sumber itu tidak percuma dan kunci sudah diletakkan di atasnya, maka benang menunggu sehingga kunci ini dilepaskan. Kelas kunci melaksanakan antara muka Lockyang mentakrifkan kaedah berikut:
  • void lock():menunggu sehingga kunci diperolehi
  • boolean tryLock():cuba mendapatkan kunci; jika kunci diperoleh, ia kembali benar . Jika kunci tidak diperoleh, ia mengembalikan palsu . Tidak seperti kaedah, lock()ia tidak menunggu untuk memperoleh kunci jika tidak tersedia
  • void unlock():menanggalkan kunci
  • Condition newCondition():mengembalikan objek Conditionyang dikaitkan dengan kunci semasa
Organisasi mengunci dalam kes umum agak mudah: untuk mendapatkan kunci, kaedah dipanggil lock(), dan selepas selesai bekerja dengan sumber yang dikongsi, kaedah itu dipanggil unlock(), yang melepaskan kunci. Objek Conditionmembolehkan anda menguruskan penyekatan. Sebagai peraturan, untuk bekerja dengan kunci, kelas ReentrantLockdaripada pakej digunakan. java.util.concurrent.locks.Kelas ini melaksanakan antara muka Lock. Mari kita lihat menggunakan Java Lock API menggunakan program kecil sebagai contoh: Jadi, katakan kita mempunyai kelas Resourcedengan beberapa kaedah dan kaedah selamat benang di mana keselamatan benang tidak diperlukan.
public class Resource {

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

    public void doLogging(){
        // потокобезопасность для логгирования нам не требуется
    }
}
Sekarang mari kita ambil kelas yang melaksanakan antara muka Runnabledan menggunakan kaedah kelas 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();
    }
}
Sekarang mari kita tulis semula program di atas menggunakan API Kunci dan bukannya 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();
    }

}
Seperti yang anda boleh lihat daripada program, kami menggunakan kaedah tryLock()untuk memastikan bahawa utas hanya menunggu untuk jangka masa tertentu. Jika ia tidak mendapat kunci pada objek, ia hanya log dan keluar. Satu lagi perkara penting. Anda mesti menggunakan blok try-finallyuntuk memastikan bahawa kunci akan dilepaskan walaupun kaedah doSomething()membuang pengecualian. Sumber:

11. Apakah mutex?

Mutex ialah objek khas untuk menyegerakkan benang/proses. Ia boleh mengambil masa dua keadaan - sibuk dan bebas. Untuk memudahkan, mutex ialah pembolehubah boolean yang mengambil dua nilai: sibuk (benar) dan bebas (salah). Apabila benang mahukan pemilikan eksklusif sesuatu objek, ia menandakan muteknya sebagai sibuk dan apabila ia selesai bekerja dengannya, ia menandakan muteknya sebagai bebas. Mutex dilampirkan pada setiap objek di Jawa. Hanya mesin Java yang mempunyai akses terus ke mutex. Ia tersembunyi daripada pengaturcara.

12. Apakah itu monitor?

Monitor ialah mekanisme khas (sekeping kod) - tambahan pada mutex, yang memastikan operasi yang betul dengannya. Lagipun, tidak cukup untuk menandakan bahawa objek itu sibuk; kita juga mesti memastikan bahawa benang lain tidak cuba menggunakan objek sibuk. Di Java, monitor dilaksanakan menggunakan kata kunci synchronized. Apabila kita menulis blok yang disegerakkan, pengkompil Java menggantikannya dengan tiga keping kod:
  1. Pada permulaan blok synchronized, kod ditambahkan yang menandakan mutex sebagai sibuk.
  2. Di penghujung blok, synchronizedkod ditambahkan yang menandakan mutex sebagai percuma.
  3. Sebelum blok, synchronizedkod ditambahkan yang menyemak sama ada mutex sibuk, maka benang mesti menunggu untuk dilepaskan.
Bahagian 1
Komen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION