最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java中關(guān)于線程安全的三種解決方式

 更新時(shí)間:2021年09月14日 08:58:42   作者:威斯布魯克.猩猩  
這篇文章主要介紹了Java中關(guān)于線程安全的三種解決方式,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

三個(gè)窗口賣票的例子解決線程安全問(wèn)題

  • 問(wèn)題:買票過(guò)程中,出現(xiàn)了重票、錯(cuò)票-->出現(xiàn)了線程的安全問(wèn)題
  • 問(wèn)題出現(xiàn)的原因:當(dāng)某個(gè)線程操作車票的過(guò)程中,尚未操作完成時(shí),其他線程參與進(jìn)來(lái),也操作車票
  • 如何解決:當(dāng)一個(gè)線程a在操作ticket的時(shí)候,其他線程不能參與進(jìn)來(lái),知道線程a操作完ticket時(shí),其他線程才可以開始操作ticket,這種情況即使線程a出現(xiàn)了阻塞,也不能被改變
  • 在Java中,我們通過(guò)同步機(jī)制,來(lái)解決線程的安全問(wèn)題。(線程安全問(wèn)題的前提:有共享數(shù)據(jù))

方式一:同步代碼塊

synchronized(同步監(jiān)視器){
//需要被同步的代碼(或操作共享數(shù)據(jù)的代碼)
}

說(shuō)明:

1.操作共享數(shù)據(jù)的代碼,即為需要被同步的代碼(不能包含代碼多了(變成單線程會(huì)效率低,也有可能會(huì)出錯(cuò)),也不能包含代碼少了(沒(méi)包的會(huì)阻塞))

2.共享數(shù)據(jù):多個(gè)線程共同操作的變量。比如:ticket就是共享數(shù)據(jù)

3.同步監(jiān)視器,俗稱:鎖。任何一個(gè)類的對(duì)象,都可以充當(dāng)鎖。

要求:多個(gè)線程必須要共用同一把鎖。(特別注意!?。。?!)
補(bǔ)充:在實(shí)現(xiàn)Runnable接口創(chuàng)建多線程的方式中,我們可以考慮使用(具體問(wèn)題具體分析)this充當(dāng)同步監(jiān)視器

class window1 implements Runnable{
    private int ticket = 100;
//    Object obj = new Object();
    @Override
    public void run() {
        while (true){
            synchronized (this) {//此時(shí)的this:唯一的Window1的對(duì)象
//            synchronized(obj) {
                if (ticket > 0) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "賣票,票號(hào)為:" + ticket);
                    ticket--;
                } else {
                    break;
                }
            }
        }
    }
}
public class WindowTest1 {
    public static void main(String[] args) {
        window1 w = new window1();//只造了一個(gè)對(duì)象,所以100張票共享
        Thread t1 = new Thread(w);
        Thread t2 = new Thread(w);
        Thread t3 = new Thread(w);
        t1.setName("線程1");
        t2.setName("線程2");
        t3.setName("線程3");
        t1.start();
        t2.start();
        t3.start();
    }
}
class Window extends Thread{
    private static int ticket = 100;//三個(gè)窗口共享:聲明為static
    private static Object obj = new Object();
    @Override
    public void run() {
        while(true) {
//                synchronized (obj) {
              synchronized (Window.class){//Class clazz = Window.class,Window.class只會(huì)加載一次
//              synchronized (this) {//錯(cuò)誤的方式:this代表著t1,t2,t3三個(gè)對(duì)象
                        if (ticket > 0) {
                            try {
                                Thread.sleep(100);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            System.out.println(getName() + ":賣票,票號(hào)為:" + ticket);
                            ticket--;
                        } else {
                            break;
                        }
                    }
                }
        }
    }
public class WindowTest {
    public static void main(String[] args) {
        Window t1 = new Window();
        Window t2 = new Window();
        Window t3 = new Window();
        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");
        t1.start();
        t2.start();
        t3.start();
    }
}

方式二:同步方法

如果操作共享數(shù)據(jù)的代碼完整的聲明在一個(gè)方法中,我們不妨將此方法聲明同步的。
4.同步的方式,解決了線程的安全問(wèn)題。---->好處
操作同步代碼時(shí),只能有一個(gè)線程參與,其他線程等待。相當(dāng)于是一個(gè)單線程的過(guò)程,效率低。--->局限性

關(guān)于同步方法的總結(jié):
1.同步方法仍然涉及到同步監(jiān)視器,只是不需要我們顯式的聲明。
2.非靜態(tài)的同步方法,同步監(jiān)視器是:this
靜態(tài)的同步方法,同步監(jiān)視器是:當(dāng)前類本身

class window3 implements Runnable{
    private int ticket = 100;
    @Override
    public void run() {
        while (true){
            show();
        }
    }
    public synchronized void show(){//同步監(jiān)視器:this(未顯示聲明而已)
        if (ticket > 0) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "賣票,票號(hào)為:" + ticket);
            ticket--;
        }
    }
}
public class WindowTest3 {
    public static void main(String[] args) {
        window3 w = new window3();
        Thread t1 = new Thread(w);
        Thread t2 = new Thread(w);
        Thread t3 = new Thread(w);
        t1.setName("線程1");
        t2.setName("線程2");
        t3.setName("線程3");
        t1.start();
        t2.start();
        t3.start();
    }
}
class Window4 extends Thread{
    private static int ticket = 100;//三個(gè)窗口共享:聲明為static
    @Override
    public void run() {
        while(true){
           show();
        }
    }
    private static synchronized void show() {//同步監(jiān)視器:Window4.class(類)
//        private synchronized void show() {//同步監(jiān)視器:t1,t2,t3。此種解決方式是錯(cuò)誤的
        if(ticket > 0){
            System.out.println(Thread.currentThread().getName() + ":賣票,票號(hào)為:" + ticket);
            ticket--;
        }
    }
}
public class WindowTest4 {
    public static void main(String[] args) {
        Window4 t1 = new Window4();
        Window4 t2 = new Window4();
        Window4 t3 = new Window4();
        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");
        t1.start();
        t2.start();
        t3.start();
    }
}

方式三:Lock鎖---JDK5.0新增

JDK5.0開始,Java提供了更強(qiáng)大的線程同步機(jī)制---通過(guò)顯式定義同步鎖對(duì)象來(lái)實(shí)現(xiàn)同步,同步鎖使用Lock對(duì)象充當(dāng)。

java.util.concurrent.locks接口是控制多個(gè)線程對(duì)共享資源進(jìn)行訪問(wèn)的工具。鎖提供了對(duì)共享資源的獨(dú)占訪問(wèn),每次只能有一個(gè)線程對(duì)Lock對(duì)象加鎖,線程開始訪問(wèn)共享資源之前應(yīng)先獲得Lock對(duì)象

ReentrantLock類實(shí)現(xiàn)了Lock,它擁有與synchronized相同的并發(fā)性和內(nèi)存語(yǔ)義,在實(shí)現(xiàn)線程安全的控制中,比較常用的是ReentrantLock,可以顯式加鎖,釋放鎖。

class Window implements Runnable{
    private int ticket = 100;
    //1.實(shí)例化ReentrantLock
    private ReentrantLock lock = new ReentrantLock();
    @Override
    public void run() {
        while (true){
            try{
                //2.調(diào)用鎖定方法:lock()
                lock.lock();
                if(ticket > 0){
                    try {
                        Thread.sleep(100);
                     }catch (InterruptedException e){
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "售票,票號(hào)為:" + ticket);
                    ticket--;
                }else{
                    break;
                }
            }  finally{
                //3.調(diào)用解鎖方法:unlock();
                lock.unlock();
            }
        }
    }
}
public class LockTest {
    public static void main(String[] args) {
        Window w = new Window();
        Thread t1 = new Thread(w);
        Thread t2 = new Thread(w);
        Thread t3 = new Thread(w);
        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");
        t1.start();
        t2.start();
        t3.start();
    }
}

線程的死鎖問(wèn)題

1.死鎖的理解:不同的線程分別占用對(duì)方需要的同步資源不放棄,都在等待對(duì)方放棄自己的需要
的同步資源,就形成了線程的死鎖。
2.說(shuō)明:
>出現(xiàn)死鎖后,不會(huì)出現(xiàn)異常,不會(huì)出現(xiàn)提示,只是所有的線程都處于阻塞狀態(tài),無(wú)法繼續(xù)
>我們使用同步時(shí),要避免出現(xiàn)死鎖

3.解決方法

A.專門的算法、原則 B.盡量減少同步資源的定義 C.盡量避免嵌套同步

public class ThreadTest {
    public static void main(String[] args) {
        StringBuffer s1 = new StringBuffer();
        StringBuffer s2 = new StringBuffer();
        new Thread(){//匿名的方式繼承
            @Override
            public void run() {
               synchronized(s1){
                   s1.append("a");
                   s2.append("1");
                   try {
                       Thread.sleep(100);//增加死鎖出現(xiàn)概率
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   }
                   synchronized (s2){
                       s1.append("b");
                       s2.append("2");
                       System.out.println(s1);
                       System.out.println(s2);
                   }
               }
            }
        }.start();
        new Thread(new Runnable(){//匿名的方式實(shí)現(xiàn)Runnable接口
            @Override
            public void run() {
                synchronized (s2){
                    s1.append("c");
                    s2.append("3");
                    try {
                        Thread.sleep(100);//增加死鎖出現(xiàn)概率
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (s1){
                        s1.append("d");
                        s2.append("4");
                        System.out.println(s1);
                        System.out.println(s2);
                    }
                }
            }
        }).start();
    }
}

synchronized和Lock的對(duì)比

1.Lock是顯示鎖(手動(dòng)開啟和關(guān)閉鎖,別忘記關(guān)閉鎖),synchronized是隱式鎖,出了作用域自動(dòng)釋放

2.Lock只有代碼塊鎖,synchronized有代碼塊鎖和方法鎖

3.使用Lock鎖,JVM將花費(fèi)較少的時(shí)間來(lái)調(diào)度線程,性能更好。并且具有更好的拓展性(提供更多的子類)

4.synchronized 與 Lock的異同?

相同:二者都可以解決線程安全問(wèn)題

不同:synchronized機(jī)制在執(zhí)行完相應(yīng)的同步代碼以后,自動(dòng)的釋放同步監(jiān)視器 Lock需要手動(dòng)的啟動(dòng)同步(lock()),同時(shí)結(jié)束同步也需要手動(dòng)的實(shí)現(xiàn)(unlock())

優(yōu)先使用順序: Lock ->同步代碼塊(已經(jīng)進(jìn)入了方法體,分配了相應(yīng)資源) ->同步方法(在方法體之外)

到此這篇關(guān)于Java中關(guān)于線程安全的三種解決方式的文章就介紹到這了,更多相關(guān)Java 線程安全內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java設(shè)計(jì)模式之代理模式

    Java設(shè)計(jì)模式之代理模式

    這篇文章介紹了Java設(shè)計(jì)模式之代理模式,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-09-09
  • java中CompleteFuture與Future的區(qū)別小結(jié)

    java中CompleteFuture與Future的區(qū)別小結(jié)

    本文主要介紹了java中CompleteFuture與Future的區(qū)別小結(jié),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-12-12
  • Spring Security實(shí)現(xiàn)自動(dòng)登陸功能示例

    Spring Security實(shí)現(xiàn)自動(dòng)登陸功能示例

    自動(dòng)登錄在很多網(wǎng)站和APP上都能用的到,解決了用戶每次輸入賬號(hào)密碼的麻煩。本文就使用Spring Security實(shí)現(xiàn)自動(dòng)登陸功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • SpringBoot 如何優(yōu)雅的實(shí)現(xiàn)跨服務(wù)器上傳文件的示例

    SpringBoot 如何優(yōu)雅的實(shí)現(xiàn)跨服務(wù)器上傳文件的示例

    這篇文章主要介紹了SpringBoot 如何優(yōu)雅的實(shí)現(xiàn)跨服務(wù)器上傳文件的示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2006-11-11
  • mybatis-xml映射文件及mybatis動(dòng)態(tài)sql詳解

    mybatis-xml映射文件及mybatis動(dòng)態(tài)sql詳解

    XML映射文件的名稱與Mapper接口名稱一致,并且將XML映射文件和Mapper接口放置在相同包下(同包同名),這篇文章主要介紹了mybatis-xml映射文件及mybatis動(dòng)態(tài)sql的相關(guān)知識(shí),感興趣的朋友跟隨小編一起看看吧
    2024-12-12
  • SpringBoot的@Value給靜態(tài)變量注入application.properties屬性值

    SpringBoot的@Value給靜態(tài)變量注入application.properties屬性值

    這篇文章主要介紹了SpringBoot的@Value給靜態(tài)變量注入application.properties屬性值,Spring是一個(gè)開源的框架,主要是用來(lái)簡(jiǎn)化開發(fā)流程,通過(guò)IOC,依賴注入(DI)和面向接口實(shí)現(xiàn)松耦合,需要的朋友可以參考下
    2023-05-05
  • mybatis攔截器實(shí)現(xiàn)數(shù)據(jù)權(quán)限項(xiàng)目實(shí)踐

    mybatis攔截器實(shí)現(xiàn)數(shù)據(jù)權(quán)限項(xiàng)目實(shí)踐

    本文主要介紹了mybatis攔截器實(shí)現(xiàn)數(shù)據(jù)權(quán)限項(xiàng)目實(shí)踐,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • Java詳細(xì)講解包的作用以及修飾符的介紹

    Java詳細(xì)講解包的作用以及修飾符的介紹

    本文主要講述的是包的使用和注意事項(xiàng)和四種訪問(wèn)修飾符public,protected,默認(rèn)的,private的訪問(wèn)范圍及實(shí)例,感興趣的朋友一起來(lái)看看
    2022-05-05
  • 使用javaMail實(shí)現(xiàn)發(fā)送郵件

    使用javaMail實(shí)現(xiàn)發(fā)送郵件

    這篇文章主要為大家詳細(xì)介紹了使用javaMail實(shí)現(xiàn)發(fā)送郵件,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • java通過(guò)ssh連接執(zhí)行shell命令,文件傳輸方式

    java通過(guò)ssh連接執(zhí)行shell命令,文件傳輸方式

    這篇文章主要介紹了java通過(guò)ssh連接執(zhí)行shell命令,文件傳輸方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-08-08

最新評(píng)論

阿拉尔市| 滦南县| 夏邑县| 闽侯县| 达日县| 霍州市| 丰县| 胶州市| 茌平县| 博白县| 荣昌县| 青海省| 东乌珠穆沁旗| 新民市| 铁岭县| 密山市| 大宁县| 读书| 凉山| 南岸区| 郓城县| 密云县| 宁乡县| 上高县| 辉南县| 武功县| 耒阳市| 娄烦县| 英山县| 新巴尔虎右旗| 嘉兴市| 双江| 上高县| 靖远县| 江津市| 汉阴县| 白城市| 枣阳市| 开远市| 靖宇县| 新昌县|