1. 并發(fā)編程的三大核心問題

        共 3737字,需瀏覽 8分鐘

         ·

        2022-07-04 18:30

        并發(fā)編程并不是一項孤立存在的技術(shù),也不是脫離現(xiàn)實生活場景而提出的一項技術(shù)。

        相反,并發(fā)編程是一項綜合性的技術(shù),同時,它與現(xiàn)實生活中 的場景有著緊密的聯(lián)系。

        并發(fā)編程有三大核心問題

        • 分工問題

        • 同步問題

        • 互斥問題

        本文就對這三大核心問題進行簡單的介紹。 


        1

        分工問題

        關(guān)于分工,比較官方的解釋是:一個比較大的任務(wù)被拆分成多個大小合適的任務(wù),這些大小合適的任務(wù)被交給合適的線程去執(zhí)行。

        分工強調(diào)的是執(zhí)行的性能。 

        類比現(xiàn)實案例

        可以類比現(xiàn)實生活中的場景來理解分工,例如,如果你是一家上市公司的 CEO,那么,你的主要工作就是規(guī)劃公司的戰(zhàn)略方向和管理好公司。就如何管理好公司而言,涉及的任務(wù)就比較多了。

        這里,可以將管理好公司看作一個很大的任務(wù),這個很大的任務(wù)可以包括人員招聘與管理、 產(chǎn)品設(shè)計、產(chǎn)品開發(fā)、產(chǎn)品運營、產(chǎn)品推廣、稅務(wù)統(tǒng)計和計算等。如果將這些工作任務(wù)都交給 CEO一個人去做,那么估計 CEO 會被累趴下的。CEO一人做完公司所有日常工作如圖1所示。 

        圖1 CEO 一人做完公司所有日常工作 

        如圖1 所示,公司 CEO 一個人做完公司所有日常工作是一種非常不可取的方式,這將導(dǎo)致公司無法正常經(jīng)營,那么應(yīng)該如何做呢? 

        有一種很好的方式是分解公司的日常工作,將人員招聘與管理工作交給人力資源部,將產(chǎn) 品設(shè)計工作交給設(shè)計部,將產(chǎn)品開發(fā)工作交給研發(fā)部,將產(chǎn)品運營和產(chǎn)品推廣工作分別交給運 營部和市場部,將公司的稅務(wù)統(tǒng)計和計算工作交給財務(wù)部。 

        這樣,CEO 的重點工作就變成了及時了解各部門的工作情況,統(tǒng)籌并協(xié)調(diào)各部門的工作, 并思考如何規(guī)劃公司的戰(zhàn)略。

        公司分工后的日常工作如圖2所示。

        圖2 公司分工后的日常工作 

        將公司的日常工作分工后,可以發(fā)現(xiàn),各部門之間的工作是可以并行推進的。例如,在人力資源部進行員工的績效考核時,設(shè)計部和研發(fā)部正在設(shè)計和開發(fā)公司的產(chǎn)品,與此同時,公司的運營人員正在和設(shè)計人員與研發(fā)人員溝通如何更好地完善公司的產(chǎn)品,而市場部正在加大力度宣傳和推廣公司的產(chǎn)品,財務(wù)部正在統(tǒng)計和計算公司的各種財務(wù)報表等。一切都是那么有條不紊。

        所以,在現(xiàn)實生活中,安排合適的人去做合適的事情是非常重要的。映射到并發(fā)編程領(lǐng)域 也是同樣的道理。

         并發(fā)編程中的分工

        在并發(fā)編程中,同樣需要將一個大的任務(wù)拆分成若干比較小的任務(wù),并將這些小任務(wù)交給 不同的線程去執(zhí)行,如圖3所示。

        圖3 將一個大的任務(wù)拆分成若干比較小的任務(wù)

        在并發(fā)編程中,由于多個線程可以并發(fā)執(zhí)行,所以在一定程度上能夠提高任務(wù)的執(zhí)行效率。

        在并發(fā)編程領(lǐng)域,還需要注意一個問題就是:將任務(wù)分給合適的線程去做。也就是說,該由主線程執(zhí)行的任務(wù)不要交給子線程去做,否則,是解決不了問題的。

        這就好比一家公司的 CEO 將規(guī)劃公司未來的工作交給一位產(chǎn)品開發(fā)人員一樣,不僅不能規(guī)劃好公司的未來,甚至會與公司的價值觀背道而馳。

        在 Java 中,線程池、Fork/Join 框架和 Future 接口都是實現(xiàn)分工的方式。在多線程設(shè)計模式中,Guarded Suspension 模式、Thread-Per-Message 模式、生產(chǎn)者—消費者模式、兩階段終止模式、Worker-Thread 模式和 Balking 模式都是分工問題的實現(xiàn)方式。

        2

        同步問題

        在并發(fā)編程中,同步指一個線程執(zhí)行完自己的任務(wù)后,以何種方式來通知其他的線程繼續(xù)執(zhí)行任務(wù),也可以將其理解為線程之間的協(xié)作,同步強調(diào)的是執(zhí)行的性能。

        類比現(xiàn)實案例

        可以在現(xiàn)實生活中找到與并發(fā)編程中的同步問題相似的案例。

        例如,張三、李四和王五共同開發(fā)一個項目,張三是一名前端開發(fā)人員,他需要等待李四的開發(fā)接口任務(wù)完成再開始渲染 頁面,而李四又需要等待王五的服務(wù)開發(fā)工作完成再寫接口。

        也就是說,任務(wù)之間是存在依賴關(guān)系的,前面的任務(wù)完成后,才能執(zhí)行后面的任務(wù)。

        在現(xiàn)實生活中,這種任務(wù)的同步,更多的是靠人與人之間的交流和溝通來實現(xiàn)的。例如,王五的服務(wù)開發(fā)任務(wù)完成了,告訴李四,李四馬上開始執(zhí)行開發(fā)接口任務(wù)。等李四的接口開發(fā)完成后,再告訴張三,張三馬上調(diào)用李四開發(fā)的接口將返回的數(shù)據(jù)渲染到頁面上。現(xiàn)實生活中 的同步模型如圖4所示。

        圖4 現(xiàn)實生活中的同步模型

        由圖4可以看出,在現(xiàn)實生活中,張三、李四和王五的任務(wù)之間是有依賴關(guān)系的,張三渲染頁面的任務(wù)依賴李四開發(fā)接口的任務(wù)完成,李四開發(fā)接口的任務(wù)依賴王五開發(fā)服務(wù)的任務(wù)完成。

        并發(fā)編程中的同步 

        在并發(fā)編程領(lǐng)域,同步機制指一個線程的任務(wù)執(zhí)行完成后,通知其他線程繼續(xù)執(zhí)行任務(wù)的方式,并發(fā)編程同步簡易模型如圖5所示。

        圖5 并發(fā)編程同步簡易模型

        由圖5可以看出,在并發(fā)編程中,多個線程之間的任務(wù)是有依賴關(guān)系的。

        線程 A 需要阻塞等待線程 B 執(zhí)行完任務(wù)才能開始執(zhí)行任務(wù),線程 B 需要阻塞等待線程 C 執(zhí)行完任務(wù)才能開始執(zhí)行任務(wù)。線程 C 執(zhí)行完任務(wù)會喚醒線程 B 繼續(xù)執(zhí)行任務(wù),線程 B 執(zhí)行完任務(wù)會喚醒線程 A 繼續(xù)執(zhí)行任務(wù)。

        這種線程之間的同步機制,可以使用如下的 if 偽代碼來表示。

        if(依賴的任務(wù)完成){  執(zhí)行當前任務(wù) }else{  繼續(xù)等待依賴任務(wù)的執(zhí)行 

        上述 if 偽代碼所代表的含義是:當依賴的任務(wù)完成時,執(zhí)行當前任務(wù),否則,繼續(xù)等待依 賴任務(wù)的執(zhí)行。

        在實際場景中,往往需要及時判斷出依賴的任務(wù)是否已經(jīng)完成,這時就可以使用 while 循 環(huán)來代替 if 判斷, while 偽代碼如下。

        while(依賴的任務(wù)未完成){  繼續(xù)等待依賴任務(wù)的執(zhí)行 }  執(zhí)行當前任務(wù)

        上述 while 偽代碼所代表的含義是:如果依賴的任務(wù)未完成,則一直等待,直到依賴的任務(wù)完成,才執(zhí)行當前任務(wù)。

        在并發(fā)編程領(lǐng)域,同步機制有一個非常經(jīng)典的模型——生產(chǎn)者—消費者模型。如果隊列已滿,則生產(chǎn)者線程需要等待,如果隊列不滿,則需要喚醒生產(chǎn)者線程;如果隊列為空,則消費者線程需要等待,如果隊列不為空,則需要喚醒消費者。

        可以使用下面的偽代碼來表示生產(chǎn)者—消費者模型。 

        • 生產(chǎn)者偽代碼

        while(隊列已滿){  生產(chǎn)者線程等待 }  喚醒生產(chǎn)者

        • 消費者偽代碼

        while(隊列為空){  消費者等待 }  喚醒消費者

        在Java 中,Semaphore、Lock、synchronized.、CountDownLatch、CyclicBarrier、Exchanger 和 Phaser 等工具類或框架實現(xiàn)了同步機制。


        3

        互斥問題

        在并發(fā)編程中,互斥問題一般指在同一時刻只允許一個線程訪問臨界區(qū)的共享資源?;コ鈴娬{(diào)的是多個線程執(zhí)行任務(wù)時的正確性。

        類比現(xiàn)實案例

        互斥問題在現(xiàn)實中的一個典型場景就是交叉路口的多輛車匯入一個單行道,如圖6所示。

        圖6 交叉路口的多輛車匯入一個單行道 

        從圖6 可以看出,當多輛車經(jīng)過交叉路口匯入同一個單行道時,由于單行道的入口只能容納一輛車通過,所以其他的車輛需要等待前面的車輛通過單行道入口后,再依次有序通過單行道入口。這就是現(xiàn)實生活中的互斥場景。

        并發(fā)編程中的互斥

        在并發(fā)編程中,分工和同步強調(diào)的是任務(wù)的執(zhí)行性能,而互斥強調(diào)的則是執(zhí)行任務(wù)的正確性,也就是線程的安全問題。

        如果在并發(fā)編程中,多個線程同時進入臨界區(qū)訪問同一個共享變量,則可能產(chǎn)生線程安全問題,這是由線程的原子性、可見性和有序性問題導(dǎo)致的。

        而在并發(fā)編程中解決原子性、可見性和有序性問題的核心方案就是線程之間的互斥。

        例如,可以使用JVM中提供的synchronized鎖來實現(xiàn)多個線程之間的互斥,使用synchronized鎖的偽代碼如下。 

        • 修飾方法

        public synchronized void methodName(){   //省略具體方法 }

        • 修飾代碼塊

        public void methodName(){   synchronized(this){      //省略具體方法   }} 
        public void methodName(){ synchronized(obj){ //省略具體方法 } }
        public void methodName(){ synchronized(ClassName.class){ //省略具體方法 } }

        • 修飾靜態(tài)方法

        public synchronized static void staticMethodName(){   //省略具體方法 }

        除了 synchronized 鎖,Java 還提供了 ThreadLocal、CAS、原子類和以CopyOnWrite 開頭的并發(fā)容器類、Lock 鎖及讀/寫鎖等,它們都實現(xiàn)了線程的互斥機制。 


        本文節(jié)選自《深入理解高并發(fā)編程:核心原理與案例實戰(zhàn)》,主要介紹了并發(fā)編程中的三大核心問題:分工、同步和互斥,并列舉了現(xiàn)實生活中的場景進行類比,以便讀者理解這三大核心問題。歡迎閱讀此書了解更多關(guān)于并發(fā)編程的內(nèi)容。

        粉絲專享5折優(yōu)惠

        快快掃碼搶購吧!

        瀏覽 28
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
          
          

            1. 扒开腿狂躁女人爽出白浆2 | 久久人人添人人爽添人人88v | 张淑芬和兴云弄雨的故事简介 | 教室呻吟用力湿冰山校草 | 欧美成人高清在线 |