1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        Java并發(fā)編程:什么是線程安全性--基礎(chǔ)知識(shí)

        共 2402字,需瀏覽 5分鐘

         ·

        2021-08-28 14:56

        ??前言

        來(lái)自我對(duì)一位我所崇拜的大佬文章的評(píng)論:

        我:“喝罷黃河之水天上來(lái),酒醒楊柳殘?jiān)虑彝禋g,唱罷笑傲江湖祭滄海,雁渡寒潭有幾只回還”

        大佬:“年少正恰,縱碼飛騁,略江山華月,有幾人隨傅虎踞龍盤(pán)?!?/p>


        ??進(jìn)入正題

        線程或者鎖在并發(fā)編程中的作用,類似于鉚釘和工字梁在土木工程中的作用。要建筑一座堅(jiān)固的橋梁,必須正確地使用大量的鉚釘和工字梁。同理,在構(gòu)建穩(wěn)健的并發(fā)程序時(shí),必須正確地使用線程和鎖。但這些終歸只是一些機(jī)制。要編寫(xiě)線程安全的代碼,其核心在于要對(duì)狀態(tài)訪問(wèn)操作進(jìn)行管理,特別是對(duì)共享(Shared)和可變的(Mutable)狀態(tài)的訪問(wèn)。

        • 對(duì)象的狀態(tài):指存儲(chǔ)在狀態(tài)變量中的數(shù)據(jù),當(dāng)然也可能包含其他依賴對(duì)象的域。

          • 例如,某個(gè) HashMap 的狀態(tài)不僅存儲(chǔ)在 HashMap 對(duì)象本身,還存儲(chǔ)在許多 Map.Entry 對(duì)象中。在對(duì)象的狀態(tài)中包含了任何可能影響其外部可見(jiàn)行為的數(shù)據(jù)。

        • 共享Shared:共享意味著變量可以有多個(gè)線程同時(shí)訪問(wèn)。

        • 可變Mutable:意味著變量的值在其生命周期內(nèi)可以發(fā)生變化。

        注釋:討論線程安全性,更應(yīng)該側(cè)重于如何防止在數(shù)據(jù)上發(fā)生不受控的并發(fā)訪問(wèn)。一個(gè)對(duì)象是否需要是線程安全的,取決于他是否被多個(gè)線程訪問(wèn)。(指的是在程序中訪問(wèn)對(duì)象的方式,而不是對(duì)象要實(shí)現(xiàn)的功能)

        當(dāng)多個(gè)線程訪問(wèn)某個(gè)狀態(tài)變量并且其中有一個(gè)線程執(zhí)行寫(xiě)入操作時(shí),必須采用同步機(jī)制來(lái)協(xié)同這些線程對(duì)變量的訪問(wèn)。

        • 關(guān)鍵字 synchronized:提供獨(dú)占的加鎖方式。

        • voatile 類型變量:同步應(yīng)該要包括的還有,顯式鎖(Explicit Lock)以及原子變量。

        如果忽略了某一個(gè)同步的機(jī)制,可能會(huì)造成的后果,當(dāng)多個(gè)線程訪問(wèn)同一個(gè)可變的狀態(tài)變量時(shí)沒(méi)有使用合適的同步,程序就會(huì)出錯(cuò),修復(fù):

        • 不在線程之間共享該狀態(tài)變量

        • 將狀態(tài)變量修改為不可變的變量

        • 在訪問(wèn)狀態(tài)變量時(shí)使用同步

        注釋:當(dāng)設(shè)計(jì)線程安全的類時(shí),良好的面向?qū)ο蠹夹g(shù)、不可修改性,以及明晰的不變形規(guī)范都能起到一定的幫助作用。

        在編寫(xiě)并發(fā)應(yīng)用程序時(shí),一種正確的編程方法就是:首先代碼正確運(yùn)行,然后再提高代碼速度。即便如此,最好也只是當(dāng)性能測(cè)試結(jié)果和應(yīng)用需求告訴你必須提高性能,以及測(cè)量結(jié)果表明這種優(yōu)化在實(shí)際環(huán)境中確實(shí)能帶來(lái)性能提升時(shí),才進(jìn)行優(yōu)化。


        ?? 什么是線程安全性

        我們都知道:定義越正式,就越復(fù)雜,不僅很難提供由實(shí)際意義的指導(dǎo)建議,而且也很難從直觀上去理解。網(wǎng)上的“定義”有很多,比如:

        • ······ 可以在多個(gè)線程中調(diào)用,并且在線程之間不會(huì)出現(xiàn)錯(cuò)誤的交互。

        • ······ 可以同時(shí)被多個(gè)線程調(diào)用,而調(diào)用者無(wú)須執(zhí)行額外的動(dòng)作。

        也難怪我們會(huì)對(duì)線程安全性感到困惑,因?yàn)槁?tīng)起來(lái)就想“如果某個(gè)類可以在多個(gè)線程中安全的使用,那么它就是一個(gè)線程安全的類?!彪m然不存在很多爭(zhēng)議,但是有什么實(shí)際的意義和幫助么。

        “安全”的含義是什么:

        • 在線程安全的定義中,最核心的概念就是正確性。

        • 正確的含義是——某個(gè)類的行為與其規(guī)范完全一致

        我將單線程的正確性近似定義為“所見(jiàn)即所知”,在對(duì)“正確性”給出了一個(gè)較為清晰的定以后,就可以定義線程安全性:

        • 當(dāng)多個(gè)線程訪問(wèn)某個(gè)類時(shí),這個(gè)類始終都能表現(xiàn)出正確的行為,那么就稱這個(gè)類是線程安全的。

        • 當(dāng)多個(gè)線程訪問(wèn)某個(gè)類時(shí),不關(guān)于刑事環(huán)境采用何種調(diào)度方式或者這些線程將如何交替執(zhí)行,并且在主調(diào)代碼中不需要任何額外的同步或協(xié)同,這個(gè)類都能表現(xiàn)出正確的行為,那么就稱呼這個(gè)類是線程安全的。

        • 由于單線程程序也可以看成多線程程序,若某個(gè)類在單線程環(huán)境下都不是正確的,那么它肯定不會(huì)是線程安全(也就是說(shuō)一個(gè)程序首先要能正常的工作保證正確性)。


        ?簡(jiǎn)單的示例

        通常,線程安全性的需求并非來(lái)源于對(duì)縣城的直接使用,而是使用像 Servlet 這樣的框架(還有很多)。

        一個(gè)基于 Servlet 的因數(shù)分解服務(wù),并逐步擴(kuò)展功能,并確保它的線程安全性。

        一個(gè)無(wú)狀態(tài)的 Servlet

        @ThreadSafe
        public class StatelessFactorizer implements Servlet {
        public void service(ServletRequest req,ServletResponse resp) {
        BigInteger i = extractFromRequest(req);
        BigInteger[] factors = factor(i);
        encodeIntoResponse(resp,factors);
        }
        }
        復(fù)制代碼

        與大多數(shù) Servlet 相同,StatelessFactorizer 是無(wú)狀態(tài)的,它既不包含任何域,也不包含任何對(duì)其他類中域的引用。計(jì)算過(guò)程中的臨時(shí)狀態(tài)僅存在于線程棧上的局部變量中,并且只能由正在執(zhí)行的線程訪問(wèn)。訪問(wèn) StatelessFactorizer 的線程不會(huì)影響另外一個(gè)訪問(wèn)同一個(gè) StatelessFactorizer 的線程的計(jì)算結(jié)果 ,因?yàn)檫@兩個(gè)線程并沒(méi)有共享狀態(tài),就好像他們都在訪問(wèn)不同的實(shí)例。由于線程訪問(wèn)無(wú)狀態(tài)對(duì)象的行為并不會(huì)影響其他線程中操作的正確性,因此無(wú)狀態(tài)對(duì)象是線程安全的。

        • 無(wú)狀態(tài)對(duì)象一定是線程安全的。

        • 大多數(shù) Servlet 都是無(wú)狀態(tài)的,從而極大地降低了在實(shí)現(xiàn) Servlet 線程安全性時(shí)的復(fù)雜性。只有當(dāng) Servlet 在處理請(qǐng)求時(shí)需要保存一些信息線程安全性才會(huì)成為一個(gè)問(wèn)題。


        作者:Sunny_Chen
        鏈接:https://juejin.cn/post/6999423430462275592
        來(lái)源:掘金
        著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。



        瀏覽 33
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            欧美一卡二卡在线观看 | 在线观看无码 | 四虎永久在线精品免费一区二区 | 啊啊啊啊啊啊好爽 | 麻豆传媒视频免费观看网页 | 操逼123首页 | 美女操逼网页 | 国产在线观看无码 | 欧美日本亚洲国产精品 | 国产一区二区三区无码 |