国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專(zhuān)欄INFORMATION COLUMN

(二)java多線程之synchronized

Tony / 691人閱讀

摘要:本人郵箱歡迎轉(zhuǎn)載轉(zhuǎn)載請(qǐng)注明網(wǎng)址代碼已經(jīng)全部托管有需要的同學(xué)自行下載引言現(xiàn)在讓我們來(lái)考慮一個(gè)問(wèn)題如果要讓多個(gè)線程來(lái)訪問(wèn)同一份數(shù)據(jù)會(huì)發(fā)生什么現(xiàn)象呢比如的火車(chē)售票系統(tǒng)比如銀行的存取款系統(tǒng)等等都可以會(huì)出現(xiàn)多線程訪問(wèn)同一個(gè)數(shù)據(jù)的情況讓我們先模擬寫(xiě)一個(gè)

本人郵箱:
歡迎轉(zhuǎn)載,轉(zhuǎn)載請(qǐng)注明網(wǎng)址 http://blog.csdn.net/tianshi_kco
github: https://github.com/kco1989/kco
代碼已經(jīng)全部托管github有需要的同學(xué)自行下載

引言

現(xiàn)在,讓我們來(lái)考慮一個(gè)問(wèn)題,如果要讓多個(gè)線程來(lái)訪問(wèn)同一份數(shù)據(jù),會(huì)發(fā)生什么現(xiàn)象呢?比如12306的火車(chē)售票系統(tǒng),比如銀行的存取款系統(tǒng)等等.都可以會(huì)出現(xiàn)多線程訪問(wèn)同一個(gè)數(shù)據(jù)的情況.讓我們先模擬寫(xiě)一個(gè)售票系統(tǒng).

編碼

首先創(chuàng)建一個(gè)Ticket類(lèi)

增加兩個(gè)成員變量count-->表示剩余的票,buyedCount-->已經(jīng)賣(mài)出的票,并提供getter方法

增加一個(gè)buyTicket方法,用來(lái)模擬售票

public class Ticket {
    private static final int DEFAULT_TICKET_COUNT = 1000;
    private int count = DEFAULT_TICKET_COUNT; //票的總數(shù)
    private int buyedCount = 0;

    public boolean buyTicket(int count) throws InterruptedException {
            if (this.count - count < 0){
                Thread.sleep(10);
                return false;
            }else{
                this.count = this.count - count;
                Thread.sleep(1);
                this.buyedCount = this.buyedCount + count;
                return true;
            }
    }

    public int getCount() {
        return count;
    }

    public int getBuyedCount() {
        return buyedCount;
    }

    public int getAllCount(){
        return count + buyedCount;
    }
}

之后創(chuàng)建一個(gè)模擬售票的類(lèi)TicketRunnable,該類(lèi)的構(gòu)造器接收一個(gè)Ticket類(lèi)

public static class TicketRunnable implements Runnable{
    private Ticket ticket;
    private Random random;
    public TicketRunnable(Ticket ticket) {
        this.ticket = ticket;
        random = new Random();
    }

    @Override
    public void run() {
        for (int i = 0; i < 5; i ++){
            try {
                int count =  random.nextInt(10) + 1;
                boolean success = ticket.buyTicket(count);
                System.out.println(String.format("%s打算買(mǎi)%d張票,買(mǎi)票%s了,還剩下%d張票,總共賣(mài)掉%d張票, 總票數(shù)%d",
                        Thread.currentThread().getName(), count, success ? "成功" : "失敗",
                        ticket.getCount(),ticket.getBuyedCount(),ticket.getAllCount()));
                if (!success){
                    break;
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }
}

最后創(chuàng)建一個(gè)main模擬20個(gè)售票點(diǎn)同時(shí)售票

public static void main(String[] args) throws InterruptedException {
    List threads = new ArrayList<>();
    Ticket ticket = new Ticket();
    for (int i = 0; i < 20; i ++){
        threads.add(new Thread(new TicketRunnable(ticket)));
    }

    for (Thread thread : threads){
        thread.start();
    }
}

截取某一次的部分運(yùn)行結(jié)果:

Thread-1打算買(mǎi)2張票,買(mǎi)票成功了,還剩下441張票,總共賣(mài)掉558張票, 總票數(shù)999
Thread-8打算買(mǎi)1張票,買(mǎi)票成功了,還剩下441張票,總共賣(mài)掉552張票, 總票數(shù)993
Thread-6打算買(mǎi)1張票,買(mǎi)票成功了,還剩下434張票,總共賣(mài)掉559張票, 總票數(shù)993
Thread-14打算買(mǎi)7張票,買(mǎi)票成功了,還剩下431張票,總共賣(mài)掉566張票, 總票數(shù)997
Thread-6打算買(mǎi)3張票,買(mǎi)票成功了,還剩下431張票,總共賣(mài)掉569張票, 總票數(shù)1000
問(wèn)題

發(fā)現(xiàn)程序運(yùn)行確實(shí)有問(wèn)題

java提供了關(guān)鍵字synchronized可以保證數(shù)據(jù)同步,在TicketbuyTicketgetter方法前加上synchronized,之后在運(yùn)行一下程序,

Thread-13打算買(mǎi)4張票,買(mǎi)票成功了,還剩下457張票,總共賣(mài)掉543張票, 總票數(shù)1000
Thread-0打算買(mǎi)2張票,買(mǎi)票成功了,還剩下479張票,總共賣(mài)掉524張票, 總票數(shù)1000
Thread-6打算買(mǎi)4張票,買(mǎi)票成功了,還剩下444張票,總共賣(mài)掉556張票, 總票數(shù)1000
Thread-0打算買(mǎi)9張票,買(mǎi)票成功了,還剩下444張票,總共賣(mài)掉556張票, 總票數(shù)1000
Thread-6打算買(mǎi)2張票,買(mǎi)票成功了,還剩下442張票,總共賣(mài)掉558張票, 總票數(shù)1000

發(fā)現(xiàn)程序沒(méi)有問(wèn)題了

getter方法上加synchronized是因?yàn)楂@取的變量也是公共的數(shù)據(jù)

解決辦法

synchronized的另外一種用法是在方法體內(nèi)使用.在上述的例子中,在方法前加synchronized其實(shí)等效于synchronized(this){方法體},因?yàn)樵谏鲜龅睦又泄驳臄?shù)據(jù)就是Ticket ticket = new Ticket();這個(gè)變量,在Ticket類(lèi)中就相當(dāng)與變量this

還有不使用synchronized(this){方法體}中的this也可以替換為另外一個(gè)公共的變量,如在Ticket類(lèi)中定義個(gè)成員變量Object o = new Object();,然后使用synchronized(o){方法體}也可以保證數(shù)據(jù)同步.

打個(gè)比喻,比如現(xiàn)在有很多人都想進(jìn)入某一個(gè)房間的臥室(至于想干嘛,大家自己腦補(bǔ)),synchronized(對(duì)象)中的對(duì)象就是一扇門(mén),

synchronized就是給這扇門(mén)加鎖.那么不管這扇門(mén)是房間最外的大門(mén),或者是臥室的門(mén).只要所有人對(duì)這同一個(gè)門(mén)在同一個(gè)時(shí)間點(diǎn)僅僅有且只有一個(gè)能開(kāi)門(mén)或者關(guān)門(mén).那么就能保證進(jìn)入臥室的人只有一個(gè).

這里舉個(gè)反例,比如進(jìn)入臥室有兩種渠道,一種是進(jìn)前門(mén),一種是進(jìn)后門(mén).(為什么臥室有前后門(mén),肯定是有特殊用戶了,哈哈...),那么有些人對(duì)前門(mén)加鎖,另外一些人對(duì)后門(mén)加鎖.這樣就不能保證進(jìn)入臥室的人只有一個(gè)了.(悲劇說(shuō)不定就這樣發(fā)生了)

在類(lèi)的靜態(tài)方法加synchronized,等效于synchronized(類(lèi).class){方法體}

另外,我們也在在不修改Ticket的基礎(chǔ)上來(lái)保證售票數(shù)據(jù)的同步,只需要將TicketRunnable.run方法改為

public void run() {
    for (int i = 0; i < 5; i ++){
        synchronized (ticket){
            try {
                int count =  random.nextInt(10) + 1;
                boolean success = ticket.buyTicket(count);
                System.out.println(String.format("%s打算買(mǎi)%d張票,買(mǎi)票%s了,還剩下%d張票,總共賣(mài)掉%d張票, 總票數(shù)%d",
                        Thread.currentThread().getName(), count, success ? "成功" : "失敗",
                        ticket.getCount(),ticket.getBuyedCount(),ticket.getAllCount()));
                if (!success){
                    break;
                }
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

這樣也能保證售票正常,那在這里能不能把synchronized (ticket){...}改為synchronized (random){...}呢?不能,因?yàn)閞andom不是同一個(gè)對(duì)象,即各個(gè)線程只對(duì)自己的門(mén)加鎖,不能保證是對(duì)同一個(gè)門(mén)加鎖.

打賞

如果覺(jué)得我的文章寫(xiě)的還過(guò)得去的話,有錢(qián)就捧個(gè)錢(qián)場(chǎng),沒(méi)錢(qián)給我捧個(gè)人場(chǎng)(幫我點(diǎn)贊或推薦一下)

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/67064.html

相關(guān)文章

  • Java線程進(jìn)階(十八)—— J.U.Csynchronizer框架:CountDownLatc

    摘要:線程可以調(diào)用的方法進(jìn)入阻塞,當(dāng)計(jì)數(shù)值降到時(shí),所有之前調(diào)用阻塞的線程都會(huì)釋放。注意的初始計(jì)數(shù)值一旦降到,無(wú)法重置。 showImg(https://segmentfault.com/img/remote/1460000016012041); 本文首發(fā)于一世流云的專(zhuān)欄:https://segmentfault.com/blog... 一、CountDownLatch簡(jiǎn)介 CountDow...

    Elle 評(píng)論0 收藏0
  • java

    摘要:多線程編程這篇文章分析了多線程的優(yōu)缺點(diǎn),如何創(chuàng)建多線程,分享了線程安全和線程通信線程池等等一些知識(shí)。 中間件技術(shù)入門(mén)教程 中間件技術(shù)入門(mén)教程,本博客介紹了 ESB、MQ、JMS 的一些知識(shí)... SpringBoot 多數(shù)據(jù)源 SpringBoot 使用主從數(shù)據(jù)源 簡(jiǎn)易的后臺(tái)管理權(quán)限設(shè)計(jì) 從零開(kāi)始搭建自己權(quán)限管理框架 Docker 多步構(gòu)建更小的 Java 鏡像 Docker Jav...

    honhon 評(píng)論0 收藏0
  • 慕課網(wǎng)_《細(xì)說(shuō)Java線程內(nèi)存可見(jiàn)性》學(xué)習(xí)總結(jié)

    時(shí)間:2017年07月09日星期日說(shuō)明:本文部分內(nèi)容均來(lái)自慕課網(wǎng)。@慕課網(wǎng):http://www.imooc.com教學(xué)源碼:無(wú)學(xué)習(xí)源碼:https://github.com/zccodere/s... 第一章:課程簡(jiǎn)介 1-1 課程簡(jiǎn)介 課程目標(biāo)和學(xué)習(xí)內(nèi)容 共享變量在線程間的可見(jiàn)性 synchronized實(shí)現(xiàn)可見(jiàn)性 volatile實(shí)現(xiàn)可見(jiàn)性 指令重排序 as-if-seria...

    wupengyu 評(píng)論0 收藏0
  • Java開(kāi)發(fā)

    摘要:大多數(shù)待遇豐厚的開(kāi)發(fā)職位都要求開(kāi)發(fā)者精通多線程技術(shù)并且有豐富的程序開(kāi)發(fā)調(diào)試優(yōu)化經(jīng)驗(yàn),所以線程相關(guān)的問(wèn)題在面試中經(jīng)常會(huì)被提到。將對(duì)象編碼為字節(jié)流稱(chēng)之為序列化,反之將字節(jié)流重建成對(duì)象稱(chēng)之為反序列化。 JVM 內(nèi)存溢出實(shí)例 - 實(shí)戰(zhàn) JVM(二) 介紹 JVM 內(nèi)存溢出產(chǎn)生情況分析 Java - 注解詳解 詳細(xì)介紹 Java 注解的使用,有利于學(xué)習(xí)編譯時(shí)注解 Java 程序員快速上手 Kot...

    LuDongWei 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<