Rumah > Java > javaTutorial > teks badan

Apakah perangkap biasa ReentrantLock di Jawa?

王林
Lepaskan: 2023-05-10 18:55:14
ke hadapan
1622 orang telah melayarinya

Pengenalan Kunci

Kunci ialah antara muka peringkat teratas, dan semua kaedahnya adalah seperti yang ditunjukkan di bawah:

Apakah perangkap biasa ReentrantLock di Jawa?

Senarai subkelasnya adalah seperti berikut:

Apakah perangkap biasa ReentrantLock di Jawa?

Kami biasanya menggunakan ReentrantLock untuk mentakrifkan kejadiannya, Hubungan antara mereka adalah seperti yang ditunjukkan di bawah:

Apakah perangkap biasa ReentrantLock di Jawa?

PS: Sync bermaksud kunci penyegerakan, FairSync bermaksud kunci adil dan NonfairSync bermaksud kunci tidak adil.

Gunakan ReentrantLock

Mempelajari sebarang kemahiran bermula dengan menggunakannya, jadi kita tidak terkecuali Mari lihat penggunaan asas ReentrantLock dahulu:

public class LockExample {
    // 创建锁对象
    private final ReentrantLock lock = new ReentrantLock();
    public void method() {
        // 加锁操作
        lock.lock();
        try {
            // 业务代码......
        } finally {
            // 释放锁
            lock.unlock();
        }
    }
}
Salin selepas log masuk

. Selepas ReentrantLock dicipta, terdapat dua operasi utama:

  • Operasi kunci: lock()

  • Lepaskan operasi kunci : buka kunci()

Perangkap dalam ReentrantLock

1 ReentrantLock lalai kepada kunci yang tidak adil

Ramai orang akan berfikir bahawa (Terutama untuk rakan baru) , pelaksanaan lalai ReentrantLock ialah kunci adil, tetapi ini tidak berlaku secara lalai ReentrantLock ialah kunci tidak adil (ini terutamanya disebabkan oleh pertimbangan prestasi),

Sebagai contoh, seperti berikut Ini. kod:

import java.util.concurrent.locks.ReentrantLock;
public class LockExample {
    // 创建锁对象
    private static final ReentrantLock lock = new ReentrantLock();
    public static void main(String[] args) {
        // 定义线程任务
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                // 加锁
                lock.lock();
                try {
                    // 打印执行线程的名字
                    System.out.println("线程:" + Thread.currentThread().getName());
                } finally {
                    // 释放锁
                    lock.unlock();
                }
            }
        };
        // 创建多个线程
        for (int i = 0; i < 10; i++) {
            new Thread(runnable).start();
        }
    }
}
Salin selepas log masuk

Keputusan pelaksanaan program di atas adalah seperti berikut:

Apakah perangkap biasa ReentrantLock di Jawa?

Seperti yang dapat dilihat daripada di atas keputusan pelaksanaan , ReentrantLock ialah kunci yang tidak adil secara lalai. Oleh kerana nama benang ditambah mengikut susunan di mana ia dicipta, jika ia adalah kunci yang adil, maka pelaksanaan benang harus meningkat mengikut susunan Walau bagaimanapun, seperti yang dapat dilihat dari keputusan di atas, pelaksanaan dan pencetakan urutan tidak teratur ini Penerangan ReentrantLock ialah kunci yang tidak adil secara lalai.

Sangat mudah untuk menetapkan ReentrantLock sebagai kunci adil Anda hanya perlu menetapkan parameter pembinaan sebenar apabila mencipta ReentrantLock Seperti yang ditunjukkan dalam kod berikut:

rreee <🎜. >

Keputusan pelaksanaan program di atas adalah seperti berikut:

Apakah perangkap biasa ReentrantLock di Jawa?

Seperti yang dapat dilihat daripada keputusan di atas, apabila kami secara eksplisit menetapkan pembina sebenar untuk ReentrantLock Selepas melepasi parameter, ReentrantLock menjadi kunci adil, dan susunan benang memperoleh kunci menjadi teratur.

Malah, daripada kod sumber ReentrantLock, kita juga boleh melihat sama ada ia adalah kunci adil atau kunci tidak adil

Sebahagian daripada kod sumber ReentrantLock dilaksanakan seperti berikut: <. 🎜>

import java.util.concurrent.locks.ReentrantLock;
public class LockExample {
    // 创建锁对象(公平锁)
    private static final ReentrantLock lock = new ReentrantLock(true);
    public static void main(String[] args) {
        // 定义线程任务
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                // 加锁
                lock.lock();
                try {
                    // 打印执行线程的名字
                    System.out.println("线程:" + Thread.currentThread().getName());
                } finally {
                    // 释放锁
                    lock.unlock();
                }
            }
        };
        // 创建多个线程
        for (int i = 0; i < 10; i++) {
            new Thread(runnable).start();
        }
    }
}
Salin selepas log masuk
Daripada kod sumber di atas, anda boleh dilihat bahawa ReentrantLock akan mencipta kunci tidak adil secara lalai Jika nilai parameter pembinaan ditetapkan secara eksplisit kepada benar semasa penciptaan, ia akan mencipta kunci adil.

2. Lepaskan kunci masuk akhirnya

Apabila menggunakan ReentrantLock, anda mesti ingat untuk melepaskan kunci, jika tidak kunci akan diduduki selama-lamanya, dan benang lain yang menggunakan kunci akan menjadi diduduki secara kekal. Tunggu

, jadi apabila kita menggunakan ReentrantLock, kita mesti melepaskan kunci masuk akhirnya, untuk memastikan bahawa kunci akan dilepaskan.

Contoh balas

 public ReentrantLock() {
     sync = new NonfairSync();
 }
public ReentrantLock(boolean fair) {
    sync = fair ? new FairSync() : new NonfairSync();
}
Salin selepas log masuk

Keputusan pelaksanaan program di atas adalah seperti berikut:

Apakah perangkap biasa ReentrantLock di Jawa? Daripada perkara di atas, dapat dilihat daripada keputusan bahawa apabila pengecualian berlaku, kunci tidak dilepaskan secara normal, yang akan menyebabkan benang lain yang menggunakan kunci berada dalam keadaan menunggu secara kekal.

Contoh positif

import java.util.concurrent.locks.ReentrantLock;
public class LockExample {
    // 创建锁对象
    private static final ReentrantLock lock = new ReentrantLock();
    public static void main(String[] args) {
        // 加锁操作
        lock.lock();
        System.out.println("Hello,ReentrantLock.");
        // 此处会报异常,导致锁不能正常释放
        int number = 1 / 0;
        // 释放锁
        lock.unlock();
        System.out.println("锁释放成功!");
    }
}
Salin selepas log masuk

Hasil pelaksanaan program di atas adalah seperti berikut:

Apakah perangkap biasa ReentrantLock di Jawa? Daripada Ia boleh dilihat daripada keputusan di atas bahawa walaupun pengecualian berlaku dalam kaedah, ia tidak menjejaskan operasi pelepasan kunci ReentrantLock, supaya benang lain yang menggunakan kunci ini boleh memperoleh dan berjalan secara normal.

3 Kunci tidak boleh dilepaskan beberapa kali

Bilangan operasi kunci dan bilangan operasi buka kunci mesti sepadan satu dengan satu, dan kunci tidak boleh dilepaskan beberapa kali, kerana ini akan Menyebabkan program melaporkan ralat.

Contoh balas

Satu kunci sepadan dengan dua operasi buka kunci, menyebabkan atur cara melaporkan ralat dan menamatkan pelaksanaan Kod sampel adalah seperti berikut:

import java.util.concurrent.locks.ReentrantLock;
public class LockExample {
    // 创建锁对象
    private static final ReentrantLock lock = new ReentrantLock();
    public static void main(String[] args) {
        // 加锁操作
        lock.lock();
        try {
            System.out.println("Hello,ReentrantLock.");
            // 此处会报异常
            int number = 1 / 0;
        } finally {
            // 释放锁
            lock.unlock();
            System.out.println("锁释放成功!");
        }
    }
}
Salin selepas log masuk

Keputusan perlaksanaan program di atas adalah seperti berikut:

Apakah perangkap biasa ReentrantLock di Jawa? Daripada keputusan di atas, dapat dilihat bahawa apabila buka kunci kedua dilaksanakan, program melaporkan ralat dan menamatkan pelaksanaan , menyebabkan kod selepas pengecualian tidak dilaksanakan seperti biasa.

4.lock 不要放在 try 代码内

在使用 ReentrantLock 时,需要注意不要将加锁操作放在 try 代码中,这样会导致未加锁成功就执行了释放锁的操作,从而导致程序执行异常。

反例

import java.util.concurrent.locks.ReentrantLock;
public class LockExample {
    // 创建锁对象
    private static final ReentrantLock lock = new ReentrantLock();
    public static void main(String[] args) {
        try {
            // 此处异常
            int num = 1 / 0;
            // 加锁操作
            lock.lock();
        } finally {
            // 释放锁
            lock.unlock();
            System.out.println("锁释锁");
        }
        System.out.println("程序执行完成.");
    }
}
Salin selepas log masuk

以上程序的执行结果如下: 

Apakah perangkap biasa ReentrantLock di Jawa?

 从上述结果可以看出,如果将加锁操作放在 try 代码中,可能会导致两个问题:

  • 未加锁成功就执行了释放锁的操作,从而导致了新的异常;

  • 释放锁的异常会覆盖程序原有的异常,从而增加了排查问题的难度。

Atas ialah kandungan terperinci Apakah perangkap biasa ReentrantLock di Jawa?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Label berkaitan:
sumber:yisu.com
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan