亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java如何避免死鎖和競態(tài)條件的實現(xiàn)

 更新時間:2023年05月31日 15:30:30   作者:王也518  
本文主要介紹了Java如何避免死鎖和競態(tài)條件的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

在Java SE中,多線程編程是非常常見的。然而,多線程編程也會帶來一些問題,比如死鎖和競態(tài)條件。本文將介紹如何避免這些問題。

死鎖

死鎖是指兩個或多個線程互相等待對方釋放資源,從而導致程序無法繼續(xù)執(zhí)行的情況。下面是一個死鎖的例子:

public class DeadlockExample {
? ? private static Object lock1 = new Object();
? ? private static Object lock2 = new Object();
? ? public static void main(String[] args) {
? ? ? ? Thread t1 = new Thread(() -> {
? ? ? ? ? ? synchronized (lock1) {
? ? ? ? ? ? ? ? System.out.println("Thread 1 acquired lock 1");
? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? ? ? Thread.sleep(1000);
? ? ? ? ? ? ? ? } catch (InterruptedException e) {
? ? ? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? synchronized (lock2) {
? ? ? ? ? ? ? ? ? ? System.out.println("Thread 1 acquired lock 2");
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? });
? ? ? ? Thread t2 = new Thread(() -> {
? ? ? ? ? ? synchronized (lock2) {
? ? ? ? ? ? ? ? System.out.println("Thread 2 acquired lock 2");
? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? ? ? Thread.sleep(1000);
? ? ? ? ? ? ? ? } catch (InterruptedException e) {
? ? ? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? synchronized (lock1) {
? ? ? ? ? ? ? ? ? ? System.out.println("Thread 2 acquired lock 1");
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? });
? ? ? ? t1.start();
? ? ? ? t2.start();
? ? }
}

在這個例子中,線程1先獲取了鎖1,然后等待1秒鐘,接著嘗試獲取鎖2。而線程2先獲取了鎖2,然后等待1秒鐘,接著嘗試獲取鎖1。由于兩個線程互相等待對方釋放鎖,因此程序會一直卡在那里,無法繼續(xù)執(zhí)行。

為了避免死鎖,我們需要遵循以下規(guī)則:

  • 避免嵌套鎖。如果一個線程已經持有了一個鎖,那么它就不能再去獲取另一個鎖。
  • 避免持有鎖的時間過長。如果一個線程持有鎖的時間過長,那么其他線程就會被阻塞,從而導致程序性能下降。
  • 使用tryLock()方法。tryLock()方法可以嘗試獲取鎖,如果獲取失敗則立即返回,而不是一直等待。

下面是一個避免死鎖的例子:

public class AvoidDeadlockExample {
? ? private static Object lock1 = new Object();
? ? private static Object lock2 = new Object();
? ? public static void main(String[] args) {
? ? ? ? Thread t1 = new Thread(() -> {
? ? ? ? ? ? boolean acquiredLock1 = false;
? ? ? ? ? ? boolean acquiredLock2 = false;
? ? ? ? ? ? while (!acquiredLock1 || !acquiredLock2) {
? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? ? ? acquiredLock1 = tryAcquireLock(lock1);
? ? ? ? ? ? ? ? ? ? acquiredLock2 = tryAcquireLock(lock2);
? ? ? ? ? ? ? ? ? ? if (acquiredLock1 && acquiredLock2) {
? ? ? ? ? ? ? ? ? ? ? ? System.out.println("Thread 1 acquired lock 1 and lock 2");
? ? ? ? ? ? ? ? ? ? ? ? // do something
? ? ? ? ? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? ? ? ? ? Thread.sleep(100);
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? } catch (InterruptedException e) {
? ? ? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? ? ? } finally {
? ? ? ? ? ? ? ? ? ? if (acquiredLock1) {
? ? ? ? ? ? ? ? ? ? ? ? lock1.notify();
? ? ? ? ? ? ? ? ? ? ? ? lock1 = null;
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? if (acquiredLock2) {
? ? ? ? ? ? ? ? ? ? ? ? lock2.notify();
? ? ? ? ? ? ? ? ? ? ? ? lock2 = null;
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? });
? ? ? ? Thread t2 = new Thread(() -> {
? ? ? ? ? ? boolean acquiredLock1 = false;
? ? ? ? ? ? boolean acquiredLock2 = false;
? ? ? ? ? ? while (!acquiredLock1 || !acquiredLock2) {
? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? ? ? acquiredLock1 = tryAcquireLock(lock1);
? ? ? ? ? ? ? ? ? ? acquiredLock2 = tryAcquireLock(lock2);
? ? ? ? ? ? ? ? ? ? if (acquiredLock1 && acquiredLock2) {
? ? ? ? ? ? ? ? ? ? ? ? System.out.println("Thread 2 acquired lock 1 and lock 2");
? ? ? ? ? ? ? ? ? ? ? ? // do something
? ? ? ? ? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? ? ? ? ? Thread.sleep(100);
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? } catch (InterruptedException e) {
? ? ? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? ? ? } finally {
? ? ? ? ? ? ? ? ? ? if (acquiredLock1) {
? ? ? ? ? ? ? ? ? ? ? ? lock1.notify();
? ? ? ? ? ? ? ? ? ? ? ? lock1 = null;
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? if (acquiredLock2) {
? ? ? ? ? ? ? ? ? ? ? ? lock2.notify();
? ? ? ? ? ? ? ? ? ? ? ? lock2 = null;
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? });
? ? ? ? t1.start();
? ? ? ? t2.start();
? ? }
? ? private static boolean tryAcquireLock(Object lock) throws InterruptedException {
? ? ? ? synchronized (lock) {
? ? ? ? ? ? if (lock == lock1 && lock2 == null) {
? ? ? ? ? ? ? ? lock2 = lock;
? ? ? ? ? ? ? ? return true;
? ? ? ? ? ? } else if (lock == lock2 && lock1 == null) {
? ? ? ? ? ? ? ? lock1 = lock;
? ? ? ? ? ? ? ? return true;
? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? lock.wait();
? ? ? ? ? ? ? ? return false;
? ? ? ? ? ? }
? ? ? ? }
? ? }
}

在這個例子中,我們使用了tryAcquireLock()方法來嘗試獲取鎖。如果獲取成功,則執(zhí)行相應的操作;否則等待一段時間后再次嘗試獲取鎖。當一個線程成功獲取了鎖1和鎖2后,就可以執(zhí)行相應的操作了。在釋放鎖的時候,我們需要將鎖的引用設置為null,并調用notify()方法來喚醒其他線程。

競態(tài)條件

競態(tài)條件是指多個線程同時訪問共享資源,從而導致程序出現(xiàn)不可預期的結果。下面是一個競態(tài)條件的例子:

public class RaceConditionExample {
? ? private static int count = 0;
? ? public static void main(String[] args) {
? ? ? ? Thread t1 = new Thread(() -> {
? ? ? ? ? ? for (int i = 0; i < 100000; i++) {
? ? ? ? ? ? ? ? count++;
? ? ? ? ? ? }
? ? ? ? });
? ? ? ? Thread t2 = new Thread(() -> {
? ? ? ? ? ? for (int i = 0; i < 100000; i++) {
? ? ? ? ? ? ? ? count++;
? ? ? ? ? ? }
? ? ? ? });
? ? ? ? t1.start();
? ? ? ? t2.start();
? ? ? ? try {
? ? ? ? ? ? t1.join();
? ? ? ? ? ? t2.join();
? ? ? ? } catch (InterruptedException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? }
? ? ? ? System.out.println("Count: " + count);
? ? }
}

在這個例子中,我們創(chuàng)建了兩個線程,它們分別對count變量進行100000次加1操作。由于這兩個線程是并發(fā)執(zhí)行的,因此它們可能會同時訪問count變量,從而導致程序出現(xiàn)不可預期的結果。
為了避免競態(tài)條件,我們需要使用同步機制。Java中的同步機制包括synchronized關鍵字和Lock接口。下面是一個使用synchronized關鍵字的例子:

public class AvoidRaceConditionExample {
? ? private static int count = 0;
? ? public static void main(String[] args) {
? ? ? ? Thread t1 = new Thread(() -> {
? ? ? ? ? ? for (int i = 0; i < 100000; i++) {
? ? ? ? ? ? ? ? synchronized (AvoidRaceConditionExample.class) {
? ? ? ? ? ? ? ? ? ? count++;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? });
? ? ? ? Thread t2 = new Thread(() -> {
? ? ? ? ? ? for (int i = 0; i < 100000; i++) {
? ? ? ? ? ? ? ? synchronized (AvoidRaceConditionExample.class) {
? ? ? ? ? ? ? ? ? ? count++;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? });
? ? ? ? t1.start();
? ? ? ? t2.start();
? ? ? ? try {
? ? ? ? ? ? t1.join();
? ? ? ? ? ? t2.join();
? ? ? ? } catch (InterruptedException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? }
? ? ? ? System.out.println("Count: " + count);
? ? }
}

在這個例子中,我們使用synchronized關鍵字來保證對count變量的訪問是同步的。當一個線程獲取了鎖之后,其他線程就必須等待該線程釋放鎖之后才能獲取鎖。這樣就可以避免競態(tài)條件了。

總結

在Java SE中,多線程編程是非常常見的。然而,多線程編程也會帶來一些問題,比如死鎖和競態(tài)條件。為了避免這些問題,我們需要遵循一些規(guī)則,比如避免嵌套鎖、避免持有鎖的時間過長、使用tryLock()方法等。另外,我們還可以使用同步機制來避免競態(tài)條件。在實際開發(fā)中,我們需要根據(jù)具體的情況選擇合適的方法來避免這些問題。

到此這篇關于Java如何避免死鎖和競態(tài)條件的實現(xiàn)的文章就介紹到這了,更多相關Java 避免死鎖和競態(tài)條件內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • 基于HttpServletRequest 相關常用方法的應用

    基于HttpServletRequest 相關常用方法的應用

    本篇文章小編為大家介紹,基于HttpServletRequest 相關常用方法的應用,需要的朋友參考下
    2013-04-04
  • java并發(fā)編程之深入理解Synchronized的使用

    java并發(fā)編程之深入理解Synchronized的使用

    文詳細講述了線程、進程的關系及在操作系統(tǒng)中的表現(xiàn),這是多線程學習必須了解的基礎。本文將接著講一下Java線程同步中的一個重要的概念synchronized,希望能夠給你有所幫助
    2021-06-06
  • 詳解java中String值為空字符串與null的判斷方法

    詳解java中String值為空字符串與null的判斷方法

    這篇文章主要介紹了詳解java中String值為空字符串與null的判斷方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-04-04
  • Java中的CGLIB動態(tài)代理的使用及原理詳解

    Java中的CGLIB動態(tài)代理的使用及原理詳解

    這篇文章主要介紹了Java中的CGLIB動態(tài)代理的使用及原理詳解,CGLIB是一個功能強大,高性能的代碼生成包,它為沒有實現(xiàn)接口的類提供代理,為JDK的動態(tài)代理提供了很好的補充,需要的朋友可以參考下
    2023-09-09
  • MyBatis-plus使用lambda條件構造器報錯問題及解決

    MyBatis-plus使用lambda條件構造器報錯問題及解決

    這篇文章主要介紹了MyBatis-plus使用lambda條件構造器報錯問題及解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • springBoot server.port=-1的含義說明

    springBoot server.port=-1的含義說明

    這篇文章主要介紹了springBoot server.port=-1的含義說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • SpringMVC攔截器快速掌握下篇

    SpringMVC攔截器快速掌握下篇

    攔截器(Interceptor)是一種動態(tài)攔截方法調用的機制,在SpringMVC中動態(tài)攔截控制器方法的執(zhí)行。本文將詳細講講SpringMVC中攔截器的概念及入門案例,感興趣的可以嘗試一下
    2022-08-08
  • springboot使用nacos的示例詳解

    springboot使用nacos的示例詳解

    這篇文章主要介紹了springboot使用nacos的示例代碼,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-12-12
  • Maven模版Bug及解決辦法

    Maven模版Bug及解決辦法

    默認,會幫我們創(chuàng)建src/main/resources 按照Maven的規(guī)范,Maven會有3個目錄,分別是: src/main/java : java源文件存放位置 src/main/resource : resource資源,如配置文件等 src/test/java : 測試代碼源文件存放位置
    2016-04-04
  • MyBatis中不建議使用where?1=1原因詳解

    MyBatis中不建議使用where?1=1原因詳解

    這篇文章主要為大家介紹了MyBatis中不建議使用where?1=1的原因詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-06-06

最新評論