一般在Java項(xiàng)目里用到鎖的場(chǎng)景不多,有朋友調(diào)侃說(shuō)用到鎖的次數(shù)還沒(méi)有面試被問(wèn)到的次數(shù)多,哈哈!
說(shuō)句難聽(tīng)話,鎖一般都很少用到,何況死鎖呢?想產(chǎn)生死鎖還是有點(diǎn)難的,需要滿足2個(gè)條件:
共享資源同時(shí)只能被一個(gè)線程使用,如果已經(jīng)有一個(gè)線程占用了資源,其余線程只能等待,直到資源被釋放。
死鎖情況肯定存在多個(gè)資源被多個(gè)線程爭(zhēng)搶的情況。
比如線程1持有了資源A,然后去等待獲取資源B,線程2持有了資源B,然后等待獲取資源A,這樣就會(huì)形成死鎖。
一般有2種方式避免死鎖:
/** * 避免死鎖,我覺(jué)得有2種方式: * 1、線程直接一把頭獲取所需要的全部鎖,不要分步 * 2、線程獲取A之后,再去獲取B,超時(shí)仍未獲取到B,則釋放A */public class AvoidDeadLock01 { private static Lock lock1 = new ReentrantLock(); private static Lock lock2 = new ReentrantLock(); public static void acquireLocks(Lock lock1, Lock lock2) { boolean isLock1Acquired = false; boolean isLock2Acquired = false; while (true) { try { isLock1Acquired = lock1.tryLock(); isLock2Acquired = lock2.tryLock(); } finally { if (isLock1Acquired && isLock2Acquired) { return; } if (isLock1Acquired) { lock1.unlock(); } if (isLock2Acquired) { lock2.unlock(); } } try { Thread.sleep(100); } catch (InterruptedException e) { throw new RuntimeException(e); } } } public static void main(String[] args) { Thread thread1 = new Thread(() -> { acquireLocks(lock1, lock2); System.out.println("=====線程1 獲取到了2把鎖====="); lock1.unlock(); lock2.unlock(); }); Thread thread2 = new Thread(() -> { acquireLocks(lock1, lock2); System.out.println("=====線程2 獲取到了2把鎖====="); lock1.unlock(); lock2.unlock(); }); thread1.start(); thread2.start(); }}
public class AvoidDeadLock02 { private static Lock lock1 = new ReentrantLock(); private static Lock lock2 = new ReentrantLock(); public static void acquireLocks(Lock lock1, Lock lock2) { boolean isLock1Acquired = false; boolean isLock2Acquired = false; try { while (true) { isLock1Acquired = lock1.tryLock(200, TimeUnit.MILLISECONDS); if (isLock1Acquired) { isLock2Acquired = lock2.tryLock(200, TimeUnit.MILLISECONDS); if (isLock2Acquired) { break; } else { lock1.unlock(); } } } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } finally { if (!isLock1Acquired || !isLock2Acquired) { if (isLock1Acquired) { lock1.unlock(); } if (isLock2Acquired) { lock2.unlock(); } } } } public static void main(String[] args) { Thread thread1 = new Thread(() -> { acquireLocks(lock1, lock2); System.out.println("=====線程1 獲取到了2把鎖====="); lock1.unlock(); lock2.unlock(); }); Thread thread2 = new Thread(() -> { acquireLocks(lock1, lock2); System.out.println("=====線程2 獲取到了2把鎖====="); lock1.unlock(); lock2.unlock(); }); thread1.start(); thread2.start(); }}
一般出現(xiàn)死鎖時(shí),可能會(huì)導(dǎo)致CPU、內(nèi)存等資源消耗過(guò)高,導(dǎo)致系統(tǒng)性能下降。也可能導(dǎo)致應(yīng)用無(wú)響應(yīng)或者假死等等,所以要從多角度進(jìn)行死鎖的排查。
首先是用top、df、free等命令查看操作系統(tǒng)的基本情況。然后可以使用jmap、jstack等命令查看JVM線程棧和堆內(nèi)存的情況。一般出現(xiàn)死鎖時(shí),會(huì)在線程棧的信息里出現(xiàn)deadlock字樣。
還可以采用VisualVM、JConsole等工具進(jìn)行排查。
本文鏈接:http://www.www897cc.com/showinfo-26-80818-0.htmlJava并發(fā):如何避免死鎖
聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問(wèn)題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com
上一篇: 構(gòu)建企業(yè)級(jí)微服務(wù)平臺(tái):實(shí)現(xiàn)可擴(kuò)展性、彈性和高效性