在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

多個線程為了同個資源打起架來了,該如何讓他們安分?

Linux愛好者 ? 來源:Linux愛好者 ? 作者:小林coding ? 2020-08-14 16:48 ? 次閱讀

前言

先來看看虛構的小故事

已經晚上 11 點了,程序員小明的雙手還在鍵盤上飛舞著,眼神依然注視著的電腦屏幕。

沒辦法這段時間公司業績增長中,需求自然也多了起來,加班自然也少不了。

天氣變化莫測,這時窗外下起了蓬勃大雨,同時閃電轟鳴。

但這一絲都沒有影響到小明,始料未及,突然一道巨大的雷一閃而過,辦公樓就這么停電了,隨后整棟樓都在回蕩著的小明那一聲撕心裂肺的「臥槽」。

此時,求小明的心里面積有多大?

等小明心里平復后,突然肚子非常的痛,想上廁所,小明心想肯定是晚上吃的某堡王有問題。

整棟樓都停了電,小明兩眼一抹黑,啥都看不見,只能靠摸墻的方法,一步一步的來到了廁所門口。

到了廁所(共享資源),由于實在太急,小明直接沖入了廁所里,用手摸索著剛好第一個門沒鎖門,便奪門而入。

這就荒唐了,這個門里面正好小紅在上著廁所,正好這個廁所門是壞了的,沒辦法鎖門。

黑暗中,小紅雖然看不見,但靠著聲音,發現自己面前的這扇門有動靜,覺得不對勁,于是鉚足了力氣,用她穿著高跟鞋腳,用力地一腳踢了過去。

小明很幸運,被踢中了「命根子」,撕心裂肺地喊出了一個字「痛」!

故事說完了,扯了那么多,實際上是為了說明,對于共享資源,如果沒有上鎖,在多線程的環境里,那么就可能會發生翻車現場。

接下來,用30+張圖,帶大家走進操作系統中避免多線程資源競爭的互斥、同步的方法。

正文

競爭與協作

在單核 CPU 系統里,為了實現多個程序同時運行的假象,操作系統通常以時間片調度的方式,讓每個進程執行每次執行一個時間片,時間片用完了,就切換下一個進程運行,由于這個時間片的時間很短,于是就造成了「并發」的現象。

并發

另外,操作系統也為每個進程創建巨大、私有的虛擬內存的假象,這種地址空間的抽象讓每個程序好像擁有自己的內存,而實際上操作系統在背后秘密地讓多個地址空間「復用」物理內存或者磁盤。

虛擬內存管理-換入換出

如果一個程序只有一個執行流程,也代表它是單線程的。當然一個程序可以有多個執行流程,也就是所謂的多線程程序,線程是調度的基本單位,進程則是資源分配的基本單位。

所以,線程之間是可以共享進程的資源,比如代碼段、堆空間、數據段、打開的文件等資源,但每個線程都有自己獨立的棧空間。

多線程

那么問題就來了,多個線程如果競爭共享資源,如果不采取有效的措施,則會造成共享數據的混亂。

我們做個小實驗,創建兩個線程,它們分別對共享變量i自增1執行10000次,如下代碼(雖然說是 C++ 代碼,但是沒學過 C++ 的同學也是看到懂的):

按理來說,i變量最后的值應該是20000,但很不幸,并不是如此。我們對上面的程序執行一下:

運行了兩次,發現出現了 i 值的結果是15173,也會出現20000的 i 值結果。

每次運行不但會產生錯誤,而且得到不同的結果。在計算機里是不能容忍的,雖然是小概率出現的錯誤,但是小概率事件它一定是會發生的,「墨菲定律」大家都懂吧。

為什么會發生這種情況?

為了理解為什么會發生這種情況,我們必須了解編譯器為更新計數器i變量生成的代碼序列,也就是要了解匯編指令的執行順序。

在這個例子中,我們只是想給i加上數字 1,那么它對應的匯編指令執行過程是這樣的:

可以發現,只是單純給i加上數字 1,在 CPU 運行的時候,實際上要執行3條指令。

設想我們的線程 1 進入這個代碼區域,它將 i 的值(假設此時是 50 )從內存加載到它的寄存器中,然后它向寄存器加 1,此時在寄存器中的 i 值是 51。

現在,一件不幸的事情發生了:時鐘中斷發生。因此,操作系統將當前正在運行的線程的狀態保存到線程的線程控制塊 TCP。

現在更糟的事情發生了,線程 2 被調度運行,并進入同一段代碼。它也執行了第一條指令,從內存獲取 i 值并將其放入到寄存器中,此時內存中 i 的值仍為 50,因此線程 2 寄存器中的 i 值也是 50。假設線程 2 執行接下來的兩條指令,將寄存器中的 i 值 + 1,然后將寄存器中的 i 值保存到內存中,于是此時全局變量 i 值是 51。

最后,又發生一次上下文切換,線程 1 恢復執行。還記得它已經執行了兩條匯編指令,現在準備執行最后一條指令。回憶一下, 線程 1 寄存器中的 i 值是51,因此,執行最后一條指令后,將值保存到內存,全局變量 i 的值再次被設置為 51。

簡單來說,增加 i (值為 50 )的代碼被運行兩次,按理來說,最后的 i 值應該是 52,但是由于不可控的調度,導致最后 i 值卻是 51。

針對上面線程 1 和線程 2 的執行過程,我畫了一張流程圖,會更明確一些:

藍色表示線程 1 ,紅色表示線程 2

互斥的概念

上面展示的情況稱為競爭條件(race condition),當多線程相互競爭操作共享變量時,由于運氣不好,即在執行過程中發生了上下文切換,我們得到了錯誤的結果,事實上,每次運行都可能得到不同的結果,因此輸出的結果存在不確定性(indeterminate)。

由于多線程執行操作共享變量的這段代碼可能會導致競爭狀態,因此我們將此段代碼稱為臨界區(critical section),它是訪問共享資源的代碼片段,一定不能給多線程同時執行。

我們希望這段代碼是互斥(mutualexclusion)的,也就說保證一個線程在臨界區執行時,其他線程應該被阻止進入臨界區,說白了,就是這段代碼執行過程中,最多只能出現一個線程。

互斥

另外,說一下互斥也并不是只針對多線程。在多進程競爭共享資源的時候,也同樣是可以使用互斥的方式來避免資源競爭造成的資源混亂。

同步的概念

互斥解決了并發進程/線程對臨界區的使用問題。這種基于臨界區控制的交互作用是比較簡單的,只要一個進程/線程進入了臨界區,其他試圖想進入臨界區的進程/線程都會被阻塞著,直到第一個進程/線程離開了臨界區。

我們都知道在多線程里,每個線程并一定是順序執行的,它們基本是以各自獨立的、不可預知的速度向前推進,但有時候我們又希望多個線程能密切合作,以實現一個共同的任務。

例子,線程 1 是負責讀入數據的,而線程 2 是負責處理數據的,這兩個線程是相互合作、相互依賴的。線程 2 在沒有收到線程 1 的喚醒通知時,就會一直阻塞等待,當線程 1 讀完數據需要把數據傳給線程 2 時,線程 1 會喚醒線程 2,并把數據交給線程 2 處理。

所謂同步,就是并發進程/線程在一些關鍵點上可能需要互相等待與互通消息,這種相互制約的等待與互通信息稱為進程/線程同步。

舉個生活的同步例子,你肚子餓了想要吃飯,你叫媽媽早點做菜,媽媽聽到后就開始做菜,但是在媽媽沒有做完飯之前,你必須阻塞等待,等媽媽做完飯后,自然會通知你,接著你吃飯的事情就可以進行了。

吃飯與做菜的同步關系

注意,同步與互斥是兩種不同的概念:

同步就好比:「操作 A 應在操作 B 之前執行」,「操作 C 必須在操作 A 和操作 B 都完成之后才能執行」等;

互斥就好比:「操作 A 和操作 B 不能在同一時刻執行」;

互斥與同步的實現和使用

在進程/線程并發執行的過程中,進程/線程之間存在協作的關系,例如有互斥、同步的關系。

為了實現進程/線程間正確的協作,操作系統必須提供實現進程協作的措施和方法,主要的方法有兩種:

鎖:加鎖、解鎖操作;

信號量:P、V 操作;

這兩個都可以方便地實現進程/線程互斥,而信號量比鎖的功能更強一些,它還可以方便地實現進程/線程同步。

使用加鎖操作和解鎖操作可以解決并發線程/進程的互斥問題。

任何想進入臨界區的線程,必須先執行加鎖操作。若加鎖操作順利通過,則線程可進入臨界區;在完成對臨界資源的訪問后再執行解鎖操作,以釋放該臨界資源。

加鎖-解鎖

根據鎖的實現不同,可以分為「忙等待鎖」和「無忙等待鎖」。

我們先來看看「忙等待鎖」的實現

在說明「忙等待鎖」的實現之前,先介紹現代 CPU 體系結構提供的特殊原子操作指令 —— 測試和置位(Test-and-Set)指令。

如果用 C 代碼表示 Test-and-Set 指令,形式如下:

測試并設置指令做了下述事情:

把old_ptr更新為new的新值

返回old_ptr的舊值;

當然,關鍵是這些代碼是原子執行。因為既可以測試舊值,又可以設置新值,所以我們把這條指令叫作「測試并設置」。

那什么是原子操作呢?原子操作就是要么全部執行,要么都不執行,不能出現執行到一半的中間狀態

我們可以運用 Test-and-Set 指令來實現「忙等待鎖」,代碼如下:

忙等待鎖的實現

我們來確保理解為什么這個鎖能工作:

第一個場景是,首先假設一個線程在運行,調用lock(),沒有其他線程持有鎖,所以flag是 0。當調用TestAndSet(flag, 1)方法,返回 0,線程會跳出 while 循環,獲取鎖。同時也會原子的設置 flag 為1,標志鎖已經被持有。當線程離開臨界區,調用unlock()將flag清理為 0。

第二種場景是,當某一個線程已經持有鎖(即flag為1)。本線程調用lock(),然后調用TestAndSet(flag, 1),這一次返回 1。只要另一個線程一直持有鎖,TestAndSet()會重復返回 1,本線程會一直忙等。當flag終于被改為 0,本線程會調用TestAndSet(),返回 0 并且原子地設置為 1,從而獲得鎖,進入臨界區。

很明顯,當獲取不到鎖時,線程就會一直 wile 循環,不做任何事情,所以就被稱為「忙等待鎖」,也被稱為自旋鎖(spin lock)。

這是最簡單的一種鎖,一直自旋,利用 CPU 周期,直到鎖可用。在單處理器上,需要搶占式的調度器(即不斷通過時鐘中斷一個線程,運行其他線程)。否則,自旋鎖在單 CPU 上無法使用,因為一個自旋的線程永遠不會放棄 CPU。

再來看看「無等待鎖」的實現

無等待鎖顧明思議就是獲取不到鎖的時候,不用自旋。

既然不想自旋,那當沒獲取到鎖的時候,就把當前線程放入到鎖的等待隊列,然后執行調度程序,把 CPU 讓給其他線程執行。

無等待鎖的實現

本次只是提出了兩種簡單鎖的實現方式。當然,在具體操作系統實現中,會更復雜,但也離不開本例子兩個基本元素。

如果你想要對鎖的更進一步理解,推薦大家可以看《操作系統導論》第 28 章鎖的內容,這本書在「微信讀書」就可以免費看。

信號量

信號量是操作系統提供的一種協調共享資源訪問的方法。

通常信號量表示資源的數量,對應的變量是一個整型(sem)變量。

另外,還有兩個原子操作的系統調用函數來控制信號量的,分別是:

P 操作:將sem減1,相減后,如果sem < 0,則進程/線程進入阻塞等待,否則繼續,表明 P 操作可能會阻塞;

V 操作:將sem加1,相加后,如果sem <= 0,喚醒一個等待中的進程/線程,表明 V 操作不會阻塞;

P 操作是用在進入臨界區之前,V 操作是用在離開臨界區之后,這兩個操作是必須成對出現的。

舉個類比,2 個資源的信號量,相當于 2 條火車軌道,PV 操作如下圖過程:

信號量與火車軌道

操作系統是如何實現 PV 操作的呢?

信號量數據結構與 PV 操作的算法描述如下圖:

PV 操作的算法描述

PV 操作的函數是由操作系統管理和實現的,所以操作系統已經使得執行 PV 函數時是具有原子性的。

PV 操作如何使用的呢?

信號量不僅可以實現臨界區的互斥訪問控制,還可以線程間的事件同步。

我們先來說說如何使用信號量實現臨界區的互斥訪問。

為每類共享資源設置一個信號量s,其初值為1,表示該臨界資源未被占用。

只要把進入臨界區的操作置于P(s)和V(s)之間,即可實現進程/線程互斥:

此時,任何想進入臨界區的線程,必先在互斥信號量上執行 P 操作,在完成對臨界資源的訪問后再執行 V 操作。由于互斥信號量的初始值為 1,故在第一個線程執行 P 操作后 s 值變為 0,表示臨界資源為空閑,可分配給該線程,使之進入臨界區。

若此時又有第二個線程想進入臨界區,也應先執行 P 操作,結果使 s 變為負值,這就意味著臨界資源已被占用,因此,第二個線程被阻塞。

并且,直到第一個線程執行 V 操作,釋放臨界資源而恢復 s 值為 0 后,才喚醒第二個線程,使之進入臨界區,待它完成臨界資源的訪問后,又執行 V 操作,使 s 恢復到初始值 1。

對于兩個并發線程,互斥信號量的值僅取 1、0 和 -1 三個值,分別表示:

如果互斥信號量為 1,表示沒有線程進入臨界區;

如果互斥信號量為 0,表示有一個線程進入臨界區;

如果互斥信號量為 -1,表示一個線程進入臨界區,另一個線程等待進入。

通過互斥信號量的方式,就能保證臨界區任何時刻只有一個線程在執行,就達到了互斥的效果。

再來,我們說說如何使用信號量實現事件同步。

同步的方式是設置一個信號量,其初值為0。

我們把前面的「吃飯-做飯」同步的例子,用代碼的方式實現一下:

媽媽一開始詢問兒子要不要做飯時,執行的是P(s1),相當于詢問兒子需不需要吃飯,由于s1初始值為 0,此時s1變成 -1,表明兒子不需要吃飯,所以媽媽線程就進入等待狀態。

當兒子肚子餓時,執行了V(s1),使得s1信號量從 -1 變成 0,表明此時兒子需要吃飯了,于是就喚醒了阻塞中的媽媽線程,媽媽線程就開始做飯。

接著,兒子線程執行了P(s2),相當于詢問媽媽飯做完了嗎,由于s2初始值是 0,則此時s2變成 -1,說明媽媽還沒做完飯,兒子線程就等待狀態。

最后,媽媽終于做完飯了,于是執行V(s2),s2信號量從 -1 變回了 0,于是就喚醒等待中的兒子線程,喚醒后,兒子線程就可以進行吃飯了。

生產者-消費者問題

生產者-消費者模型

生產者-消費者問題描述:

生產者在生成數據后,放在一個緩沖區中;

消費者從緩沖區取出數據處理;

任何時刻,只能有一個生產者或消費者可以訪問緩沖區;

我們對問題分析可以得出:

任何時刻只能有一個線程操作緩沖區,說明操作緩沖區是臨界代碼,需要互斥;

緩沖區空時,消費者必須等待生產者生成數據;緩沖區滿時,生產者必須等待消費者取出數據。說明生產者和消費者需要同步。

那么我們需要三個信號量,分別是:

互斥信號量mutex:用于互斥訪問緩沖區,初始化值為 1;

資源信號量fullBuffers:用于消費者詢問緩沖區是否有數據,有數據則讀取數據,初始化值為 0(表明緩沖區一開始為空);

資源信號量emptyBuffers:用于生產者詢問緩沖區是否有空位,有空位則生成數據,初始化值為 n (緩沖區大小);

具體的實現代碼:

如果消費者線程一開始執行P(fullBuffers),由于信號量fullBuffers初始值為 0,則此時fullBuffers的值從 0 變為 -1,說明緩沖區里沒有數據,消費者只能等待。

接著,輪到生產者執行P(emptyBuffers),表示減少 1 個空槽,如果當前沒有其他生產者線程在臨界區執行代碼,那么該生產者線程就可以把數據放到緩沖區,放完后,執行V(fullBuffers),信號量fullBuffers從 -1 變成 0,表明有「消費者」線程正在阻塞等待數據,于是阻塞等待的消費者線程會被喚醒。

消費者線程被喚醒后,如果此時沒有其他消費者線程在讀數據,那么就可以直接進入臨界區,從緩沖區讀取數據。最后,離開臨界區后,把空槽的個數 + 1。

經典同步問題

哲學家就餐問題

當初我在校招的時候,面試官也問過「哲學家就餐」這道題目,我當時聽的一臉懵逼,無論面試官怎么講述這個問題,我也始終沒聽懂,就莫名其妙的說這個問題會「死鎖」。

當然,我這回答槽透了,所以當場 game over,殘酷又悲慘故事,就不多說了,反正當時菜就是菜。

時至今日,看我來圖解這道題。

哲學家就餐的問題

先來看看哲學家就餐的問題描述:

5個老大哥哲學家,閑著沒事做,圍繞著一張圓桌吃面;

巧就巧在,這個桌子只有5支叉子,每兩個哲學家之間放一支叉子;

哲學家圍在一起先思考,思考中途餓了就會想進餐;

奇葩的是,這些哲學家要兩支叉子才愿意吃面,也就是需要拿到左右兩邊的叉子才進餐;

吃完后,會把兩支叉子放回原處,繼續思考;

那么問題來了,如何保證哲學家們的動作有序進行,而不會出現有人永遠拿不到叉子呢?

方案一

我們用信號量的方式,也就是 PV 操作來嘗試解決它,代碼如下:

上面的程序,好似很自然。拿起叉子用 P 操作,代表有叉子就直接用,沒有叉子時就等待其他哲學家放回叉子。

方案一的問題

不過,這種解法存在一個極端的問題:假設五位哲學家同時拿起左邊的叉子,桌面上就沒有叉子了, 這樣就沒有人能夠拿到他們右邊的叉子,也就說每一位哲學家都會在P(fork[(i + 1) % N ])這條語句阻塞了,很明顯這發生了死鎖的現象。

方案二

既然「方案一」會發生同時競爭左邊叉子導致死鎖的現象,那么我們就在拿叉子前,加個互斥信號量,代碼如下:

上面程序中的互斥信號量的作用就在于,只要有一個哲學家進入了「臨界區」,也就是準備要拿叉子時,其他哲學家都不能動,只有這位哲學家用完叉子了,才能輪到下一個哲學家進餐。

方案二的問題

方案二雖然能讓哲學家們按順序吃飯,但是每次進餐只能有一位哲學家,而桌面上是有 5 把叉子,按道理是能可以有兩個哲學家同時進餐的,所以從效率角度上,這不是最好的解決方案。

方案三

那既然方案二使用互斥信號量,會導致只能允許一個哲學家就餐,那么我們就不用它。

另外,方案一的問題在于,會出現所有哲學家同時拿左邊刀叉的可能性,那我們就避免哲學家可以同時拿左邊的刀叉,采用分支結構,根據哲學家的編號的不同,而采取不同的動作。

即讓偶數編號的哲學家「先拿左邊的叉子后拿右邊的叉子」,奇數編號的哲學家「先拿右邊的叉子后拿左邊的叉子」。

上面的程序,在 P 操作時,根據哲學家的編號不同,拿起左右兩邊叉子的順序不同。另外,V 操作是不需要分支的,因為 V 操作是不會阻塞的。

方案三可解決問題

方案三即不會出現死鎖,也可以兩人同時進餐。

方案四

在這里再提出另外一種可行的解決方案,我們用一個數組 state 來記錄每一位哲學家在進程、思考還是饑餓狀態(正在試圖拿叉子)。

那么,一個哲學家只有在兩個鄰居都沒有進餐時,才可以進入進餐狀態。

第i個哲學家的左鄰右舍,則由宏LEFT和RIGHT定義:

LEFT: ( i + 5 - 1 ) % 5

RIGHT: ( i + 1 ) % 5

比如 i 為 2,則LEFT為 1,RIGHT為 3。

具體代碼實現如下:

上面的程序使用了一個信號量數組,每個信號量對應一位哲學家,這樣在所需的叉子被占用時,想進餐的哲學家就被阻塞。

注意,每個進程/線程將smart_person函數作為主代碼運行,而其他take_forks、put_forks和test只是普通的函數,而非單獨的進程/線程。

方案四也可解決問題

方案四同樣不會出現死鎖,也可以兩人同時進餐。

讀者-寫者問題

前面的「哲學家進餐問題」對于互斥訪問有限的競爭問題(如 I/O 設備)一類的建模過程十分有用。

另外,還有個著名的問題是「讀者-寫者」,它為數據庫訪問建立了一個模型。

讀者只會讀取數據,不會修改數據,而寫者即可以讀也可以修改數據。

讀者-寫者的問題描述:

「讀-讀」允許:同一時刻,允許多個讀者同時讀

「讀-寫」互斥:沒有寫者時讀者才能讀,沒有讀者時寫者才能寫

「寫-寫」互斥:沒有其他寫者時,寫者才能寫

接下來,提出幾個解決方案來分析分析。

方案一

使用信號量的方式來嘗試解決:

信號量wMutex:控制寫操作的互斥信號量,初始值為 1 ;

讀者計數rCount:正在進行讀操作的讀者個數,初始化為 0;

信號量rCountMutex:控制對 rCount 讀者計數器的互斥修改,初始值為 1;

接下來看看代碼的實現:

上面的這種實現,是讀者優先的策略,因為只要有讀者正在讀的狀態,后來的讀者都可以直接進入,如果讀者持續不斷進入,則寫者會處于饑餓狀態。

方案二

那既然有讀者優先策略,自然也有寫者優先策略:

只要有寫者準備要寫入,寫者應盡快執行寫操作,后來的讀者就必須阻塞;

如果有寫者持續不斷寫入,則讀者就處于饑餓;

在方案一的基礎上新增如下變量:

信號量rMutex:控制讀者進入的互斥信號量,初始值為 1;

信號量wDataMutex:控制寫者寫操作的互斥信號量,初始值為 1;

寫者計數wCount:記錄寫者數量,初始值為 0;

信號量wCountMutex:控制 wCount 互斥修改,初始值為 1;

具體實現如下代碼:

注意,這里rMutex的作用,開始有多個讀者讀數據,它們全部進入讀者隊列,此時來了一個寫者,執行了P(rMutex)之后,后續的讀者由于阻塞在rMutex上,都不能再進入讀者隊列,而寫者到來,則可以全部進入寫者隊列,因此保證了寫者優先。

同時,第一個寫者執行了P(rMutex)之后,也不能馬上開始寫,必須等到所有進入讀者隊列的讀者都執行完讀操作,通過V(wDataMutex)喚醒寫者的寫操作。

方案三

既然讀者優先策略和寫者優先策略都會造成饑餓的現象,那么我們就來實現一下公平策略。

公平策略:

優先級相同;

寫者、讀者互斥訪問;

只能一個寫者訪問臨界區;

可以有多個讀者同時訪問臨街資源;

具體代碼實現:

看完代碼不知你是否有這樣的疑問,為什么加了一個信號量flag,就實現了公平競爭?

對比方案一的讀者優先策略,可以發現,讀者優先中只要后續有讀者到達,讀者就可以進入讀者隊列, 而寫者必須等待,直到沒有讀者到達。

沒有讀者到達會導致讀者隊列為空,即rCount==0,此時寫者才可以進入臨界區執行寫操作。

而這里flag的作用就是阻止讀者的這種特殊權限(特殊權限是只要讀者到達,就可以進入讀者隊列)。

比如:開始來了一些讀者讀數據,它們全部進入讀者隊列,此時來了一個寫者,執行P(falg)操作,使得后續到來的讀者都阻塞在flag上,不能進入讀者隊列,這會使得讀者隊列逐漸為空,即rCount減為 0。

這個寫者也不能立馬開始寫(因為此時讀者隊列不為空),會阻塞在信號量wDataMutex上,讀者隊列中的讀者全部讀取結束后,最后一個讀者進程執行V(wDataMutex),喚醒剛才的寫者,寫者則繼續開始進行寫操作。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • cpu
    cpu
    +關注

    關注

    68

    文章

    10877

    瀏覽量

    212128
  • 多線程
    +關注

    關注

    0

    文章

    278

    瀏覽量

    20016
  • 代碼
    +關注

    關注

    30

    文章

    4798

    瀏覽量

    68728

原文標題:多個線程為了同個資源打起架來了,該如何讓他們安分?

文章出處:【微信號:LinuxHub,微信公眾號:Linux愛好者】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    socket 多線程編程實現方法

    是指在同一進程中運行多個線程,每個線程可以獨立執行任務。線程共享進程的資源,如內存空間和文件句
    的頭像 發表于 11-12 14:16 ?397次閱讀

    使用LMP7721做微電流跨阻放大器,如何Guard與輸入電位?

    的NC引腳連接嗎?Guard應該與輸入端電位才能起保護作用,那么如何Guard與輸入電位?這個電路應該怎么設計?
    發表于 08-12 06:22

    ESP32-wrover-IE無法在多個線程同時去操作同一文件嗎?

    播放demo播放SD卡中已下載部分的MP3文件,demo無法播放,提示“no more data”。 請問是無法在多個線程同時去操作同一文件么?
    發表于 06-28 08:10

    探索虛擬線程:原理與實現

    虛擬線程的引入與優勢 在Loom項目之前,Java虛擬機(JVM)中的線程是通過java.lang.Thread類型來實現的,這些線程被稱為平臺線程。 然而,平臺
    的頭像 發表于 06-24 11:35 ?319次閱讀
    探索虛擬<b class='flag-5'>線程</b>:原理與實現

    一句話你理解線程和進程

    今天給大家分享一下線程與進程,主要包含以下幾部分內容:一句話說明線程和進程操作系統為什么需要進程為什么要引入線程一圖說明線程和進程的關系一句話
    的頭像 發表于 06-04 08:04 ?1237次閱讀
    一句話<b class='flag-5'>讓</b>你理解<b class='flag-5'>線程</b>和進程

    如何避免無線通信時的頻干擾?

    頻干擾是指在無線通信系統中,由于兩多個通信設備使用相同的頻率進行通信,導致信號互相干擾的現象。
    的頭像 發表于 05-22 15:35 ?1879次閱讀

    鴻蒙原生應用開發-ArkTS語言基礎類庫多線程TaskPool和Worker的對比(一)

    TaskPool(任務池)和Worker的作用是為應用程序提供一線程的運行環境,用于處理耗時的計算任務或其他密集型任務。可以有效地避免這些任務阻塞主線程,從而最大化系統的利用率,降低整體
    發表于 03-25 14:11

    RT-thread中運行了好多個線程,有的線程很長時間不執行是什么原因?

    RT-thread中運行了好多個線程,有的線程很長時間不執行,通過什么方式知道線程因為什么原因阻塞
    發表于 03-22 06:48

    java實現多線程的幾種方式

    Java實現多線程的幾種方式 多線程是指程序中包含了兩或以上的線程,每個線程都可以并行執行不同的任務或操作。Java中的多
    的頭像 發表于 03-14 16:55 ?737次閱讀

    python中5種線程鎖盤點

    線程安全是多線程或多進程編程中的一概念,在擁有共享數據的多條線程并行執行的程序中,線程安全的代碼會通過同步機制保證各個
    發表于 03-07 11:08 ?1617次閱讀
    python中5種<b class='flag-5'>線程</b>鎖盤點

    使用rt_thread nano有辦法查看線程資源占用情況嗎?

    使用rt_thread nano ,有辦法查看線程資源占用情況麼?
    發表于 02-26 06:05

    線程是什么的基本單位 進程與線程的本質區別

    線程是操作系統中處理器調度的基本單位,它代表著獨立的執行流。在一進程中,可以包含多個線程,這些線程共享相同的進程
    的頭像 發表于 02-02 16:30 ?958次閱讀

    鴻蒙OS 線程管理開發指導

    場景介紹 如果應用的業務邏輯比較復雜,可能需要創建多個線程來執行多個任務。這種情況下,代碼復雜難以維護,任務與線程的交互也會更加繁雜。要解決此問題,開發者可以使用“TaskDispat
    的頭像 發表于 01-29 16:22 ?857次閱讀

    .NET8性能優化之線程

    目前來說,沒有確切的證據證明哪個線程池好用,或者效率更高。但是開發者可以使用上面的選項來進行自己的選擇,有一測試就是在Windows線程池在比較大的機器上的IO擴展性不太好。如果你的應用程序已經
    的頭像 發表于 01-22 14:50 ?1173次閱讀

    Redis7單線程與多線程詳解

    主要是指Redis的網絡IO和鍵值對讀寫是由一線程來完成的。
    的頭像 發表于 01-16 17:33 ?1872次閱讀
    Redis7單<b class='flag-5'>線程</b>與多<b class='flag-5'>線程</b>詳解
    主站蜘蛛池模板: 又黄又爽又猛大片录像| 色视频免费观看高清完整| 天天操天天干天天爱| 亚洲精品午夜久久aaa级久久久| 午夜视频1000| 免费一级毛片在线播放不收费| 濑亚美莉vs黑人欧美视频| 国产在线视频网站| 日本欧美午夜| 日本黄色录像视频| 久青草国产手机在线观| 色老头久久久久| 求网址你懂的手机在线观看网站| 免费一级视频在线播放| 国产五月| 午夜寂寞影| 大片免费看| 嫩草网| 午夜欧美电影| 女张腿男人桶羞羞漫画| 色老头影视| 久久电影www成人网| 一级特黄aaa大片免费看| 免费在线观看a视频| 欧美午夜性春猛xxxx| 67194最新网址| 亚洲精品一区二区中文| 亚洲精品美女| 午夜免费看片| 欧美大胆一级视频| www.av在线免费观看| 玖操在线| 在线成人免费观看国产精品| 亚洲毛片网站| 久久精品男人的天堂| 午夜美女久久久久爽久久| 福利看片| 一色屋免费视频| 免费看欧美一级特黄a大片 | 五月婷婷欧美| 男人天堂欧美|