【操作系統】進程管理——用信號量機制解決問題,以生產者-消費者問題為例(個人筆記)

學習日期:2024.7.10

內容摘要:利用信號量機制解決幾個經典問題模型


目錄

引言

問題模型

生產者-消費者問題(經典)

多生產者-多消費者問題

吸煙者問題

讀者寫者問題(難點)

哲學家進餐問題(避免死鎖)


引言

在《信號量機制》章節中,我們已經學習了信號量的概念和用其實現進程同步和互斥的工作原理,下面結合實際的模型來看信號量機制如何起效。

PV操作題目分析步驟

1.關系分析。找出題目中描述的各個進程,分析它們之間的同步、互斥關系。

2.整理思路。根據各進程的操作流程缺點P、V操作的大致順序。

3.設置信號量。根據題目條件確定信號量初始值(互斥一般為1,同步一般看對應資源的初始值)

簡記口訣:

互斥:緊鄰操作,成對PV(緊鄰互斥操作,在同一進程內完成PV)

同步:前V后P,前后后前(在不同進程內進行操作以保證順序執行,在前一個進程完成后進行V操作,在后一個進程開始前進行P操作)

問題模型

生產者-消費者問題(經典)

系統中有一組生產者進程和消費者進程,生產者每次生產一個產品放入緩沖區,消費者每次從緩沖區中取出一個產品使用(“緩沖區”理解為二者共享的倉庫,“產品”理解為某種數據)

緩沖區是一個初始為空,大小固定為n,雙方共享的區域,且緩沖區是臨界資源,各進程必須互斥訪問。(原因:如果不是互斥訪問的,可能兩個生產者進程在同一片區域放入數據,導致數據覆蓋丟失)

首先分析,顯然:

①緩沖區沒滿的情況下,生產者才能生產,二者有同步關系。

②緩沖區不空的情況下,消費者才能消費,二者有同步關系。

③進程對緩沖區的訪問必須互斥。

那么,設置三個變量,一個mutex表示互斥標記,一個empty表示空閑區數目,一個full表示裝入區數目。每次生產者進程行動時,P(empty),V(full),消費者行動時則反之

這樣就能實現通過PV操作來表示資源的獲取與釋放。

注意!實現互斥是在同一進程中進行一對PV操作,在“把產品放入緩沖區/從緩沖區中取出”這一對臨界資源的訪問行為前后,成對進行。

而同步關系是在兩進程分開執行,在一個進程中執行P,另一個執行V。具體理論部分可以參考上一章。

Q:能否交換相鄰P操作的順序?

不能。假如交換了生產者的前兩個P操作的順序,若緩沖區內已經放滿產品,此時empty=0,full=n。若生產者先進行P(mutex)聲明自己獨占了緩沖區,然后P(empty)發現緩沖區的empty區不足,就會進入阻塞狀態。

之后消費者想占用緩沖區,釋放empty資源時,因為生產者已經占用了mutex,沒有釋放,因為互斥會導致無法進行V(empty)操作

這樣,生產者在等待消費者釋放empty,消費者在等待生產者解除對緩沖區的占用,雙方會無限等待下去,形成死鎖

所以表示互斥的PV部分要成對出現,成對執行,且實現互斥的P操作一定在實現同步操作的P操作之后

Q:能否交換相鄰V操作的順序?

可以,V操作不會導致進程阻塞,但是為了方便理解記憶,還是讓實現互斥的PV操作緊鄰互斥行動區為好。

Q:能否不依賴互斥標識資源mutex?

通常不行,但是特殊情況下可以。這個特殊情況就是緩沖區容量為1的情況(即empty的初始值為1),此時如果一個生產者生產了產品,執行P(empty),另一個生產者也想生產產品時,因為empty的值已經是0,就會發生阻塞,從而避免了生產者同時訪問的問題。而在生產者執行完互斥操作,V(full)之前,因為full的值為0,消費者進行P(full)時也會阻塞,避免了生產者訪問時消費者同時訪問的問題,從而不依賴mutex就能實現互斥訪問。

多生產者-多消費者問題

是生產者-消費者問題的變形,區別在于增加了若干組生產者和消費者。比如說1號生產者會生產1型商品,2號生產者生產2型商品,而1號消費者只消費1型商品,2消費者只消費2型商品。

所有的生產者和消費者仍舊共享一個緩沖區,此處的“多”指的是“多類”而不是“多個”,與上一問題的根本區別是有多類生產者和消費者。

關系分析:

①首先,同生產者-消費者問題的前提一樣,緩沖區沒滿才能生產,不空才能消費,且互斥訪問。

②根據不同資源的類型,分別PV不同的變量,來為每對生產者和消費者確立同步關系。

在分析同步問題的時候,不能從單個進程行為的角度來分析,而應該從事件角度分析。

不要想著“x號生產者生產了一個x號產品,x號消費者......”,然后設置四個同步信號量。而是從事件的角度分析,把進程的先后順序概括為事件的先后順序,在這個例子中,就是生產產品事件先于消耗產品事件。

生產產品可以是1號生產者,也可以是2號生產者,它們只需要每次占用一個倉庫空間P(empty),然后增加一個對應產品V(product_x)。同樣的,消費者也只要每次消耗一個產品P(product_x),然后釋放一個空間P(empty)就行了。最后再在互斥操作前后加上mutex的成對PV操作保證互斥,根據空間的大小設置empty的初始值,就可以解決問題了!

吸煙者問題

仍然是生產者-消費者問題的變形。更準確的來說,是“可生產多種產品的單生產者-多消費者問題”

假設一個系統有三個抽煙者進程和一個供應者進程,每個抽煙者進程不停的卷煙并抽煙,這需要三種材料:煙草、紙卷和膠水。在三個抽煙者中,第一個有煙草,第二個有紙卷,第三個有膠水。供應者會無限提供三種材料,每次將兩個材料置于桌面,而擁有剩下那個材料的抽煙者就會拿走,完成抽煙,然后給供應者一個信號告訴他完成了,供應者就會放另外兩種材料在桌上,讓三個抽煙者能夠輪流抽煙。

首先,桌子可以抽象為容量為1,互斥訪問的緩沖區。為什么放兩件東西容量為1呢?

我們將供應者供應的兩件東西看作是一個組合,則他一共供給三個組合,第一個消費者需要紙卷+膠水,定義為組合1,第二個消費者需要煙草+膠水,定義為組合2,同理得組合3。

這樣問題就抽象為了一個生產者能生產1號,2號,3號三種產品,分別對應三個消費者,要進行輪流消費,緩沖區容量為1。

關系分析:

①桌上有組合x 先于 x號消費者取走東西,且緩沖區互斥訪問。

②消費者發出完成信號 先于 生產者將下一個組合放到桌上。

Q:輪流操作如何實現?

如右圖所示,通過一個if(i==0)的選擇分支結構,和結尾的i=(i+1)%3,實現了讓i在0,1,2不斷循環變化,從而輪流執行三個部分的生產,每次產生對應的offer。補充:如果要隨機實現,可以用Random(i)

而如上圖每一個消費者每次消耗一個offer的商品P(offer_x),然后再釋放一個finish信號給生產者,保證先釋放信號,然后生產者再生產下一個產品。

之前介紹過,因為此時緩沖區的容量為1,故不需要互斥信號量mutex也可以實現互斥訪問。


讀者寫者問題(難點)

在系統中有讀者、寫者兩組并發進程,共享一個文件。多個讀者可以同時對文件執行讀操作,但是只允許一個寫者往文件中寫入信息,寫者對文件的訪問必須互斥,也不能邊寫邊讀,每個寫者在工作時都必須獨占該共享文件

與消費者進程不同,讀者進程在讀數據時,不會“消耗”數據, 所以讀者進程可以同時訪問共享數據,互不影響。

不能邊讀邊寫是因為,如果允許并發執行,讀者可能先讀了某數據的一部分,但剩下的部分被寫者覆蓋了,導致讀者所讀的數據并不是所期望的。不能同時寫的原因同生產者進程互斥原因,會相互覆蓋。

關系分析:

寫者進程和所有進程互斥,讀者進程之間不互斥

難點就在于,如何在實現寫者進程互斥的同時,讓讀者進程不互斥。

我們一步一步來:

semaphore rw=1writer(){while(1){P(rw);  //寫之前上鎖寫文件操作...V(rw);  //寫完解鎖}
}reader(){while(1){P(rw);    //讀之前上鎖讀文件操作...V(rw);  //讀完解鎖}
}

?先寫個最簡單的,但是顯然,這樣是每個進程都互斥訪問共享區,不能實現同時讀操作。

那么,要如何實現“同時讀”呢?可以設法讓后面的讀進程跳過P(rw)這一步

所以,邏輯代碼變成了這樣:

semaphore rw=1;
int count = 0;  //記錄當前有幾個讀進程在訪問文件writer(){while(1){P(rw);  //寫之前上鎖寫文件操作...V(rw);  //寫完解鎖}
}reader(){while(1){
if(count==0)  //由第一個讀進程負責上鎖P(rw);    //讀之前上鎖count++;    讀文件操作...count--;   
if(count==0)//由最后一個讀進程負責解鎖V(rw);  //讀完解鎖}
}

我們引入了一個新的變量count用來記錄當前訪問文件的讀進程數,當count==0時,訪問文件的讀進程是第一個,它負責上鎖,之后訪問的讀進程,因為count!=0,就跳過了P(rw)語句,從而可以直接進行讀文件操作。同理,當最后一個讀進程讀完時,count==0,最后一個進程進行V(rw)釋放資源,表示沒有讀進程還在操作了。

但是這樣還是有一個問題,因為讀進程是并發執行的,如果兩個讀進程同時開始執行,當第一個讀者進程P(rw)以后,還沒有來得及count++時,第二個讀進程可能已經通過了conunt的判斷語句,也進行P(rw),但是此時rw已經為0了,這會導致第二個進程阻塞。

顯然,出現上一問題的原因是,我們對count變量的檢查和賦值無法一氣呵成無法一氣呵成...?我們最初用PV操作就是為了解決進程互斥中,軟件實現方法無法一氣呵成的問題的,(詳見《進程的同步與互斥》)所以可以想到,再加一組互斥標識,保證進程能互斥的訪問count。

semaphore rw = 1;
semaphore mutex = 1;//用于保證對count變量的互斥訪問
int count = 0;  //記錄當前有幾個讀進程在訪問文件writer(){while(1){P(rw);  //寫之前上鎖寫文件操作...V(rw);  //寫完解鎖}
}reader(){while(1){P(mutex);if(count==0)  //由第一個讀進程負責上鎖P(rw);    //讀之前上鎖count++; V(mutex);   讀文件操作...P(mutex);count--;   if(count==0)//由最后一個讀進程負責解鎖V(rw);  //讀完解鎖V(mutex);}
}

?我們引入了mutex變量,來保證進程能互斥的訪問count,此時如果兩個讀進程同步訪問count,第一個進程會P(mutex)阻止其它讀進程修改count,并且在自己修改完count之后,其它進程才能進行if判斷,這樣就不會出現上述問題了。兩組對于mutex的PV操作,能夠保證進程對count的互斥訪問

但是,還有一個潛在的問題(受不了了),只要有讀進程還在讀,rw的值就始終是0,寫進程就會一直阻塞,如果一直有源源不斷的讀進程,寫進程就會饑餓。在這種算法中,讀進程是優先的。那么,該如何避免寫進程饑餓呢?就是說,怎樣能讓寫進程在想寫入的時候,在有限的等待時間內就能寫入呢?

semaphore rw = 1;
semaphore mutex = 1;//用于保證對count變量的互斥訪問
semaphore w = 1;  //用于實現“寫優先”
int count = 0;  //記錄當前有幾個讀進程在訪問文件writer(){while(1){P(w);P(rw);  //寫之前上鎖寫文件操作...V(rw);  //寫完解鎖V(w);}
}reader(){while(1){P(w);P(mutex);if(count==0)  //由第一個讀進程負責上鎖P(rw);    //讀之前上鎖count++; V(mutex);V(w);   讀文件操作...P(mutex);count--;   if(count==0)//由最后一個讀進程負責解鎖V(rw);  //讀完解鎖V(mutex);}
}

?我們又引入了一個新的變量w,用于實現寫優先。

假如三個進程讀者A,寫者,讀者B并發執行。

當讀者進程A通過了上半部分,開始進行讀文件操作時,釋放了w,占用了rw。此時寫者進程可以進行P(w)操作了,但是會被阻塞在P(rw)操作上。當讀者進程B開始運行時,因為寫進程已經進行過P(w)操作了,讀者B會在P(w)處被阻塞。

這樣當讀者A的讀操作結束時,count--后為0,讀者A會認為自己是最后一個讀進程,從而釋放rw,這樣寫者就可以執行P(rw),實現了寫者優先于讀者B執行。

此方法并不是真正的“寫優先”,只是保證了寫進程不會饑餓,相對公平的實現了先來先服務。

此處的w好比一個提供順序功能的標記,第一個讀者最開始先占用,然后在讀文件之前釋放,第二個讀者如果在寫者之后來,就會因為寫者已經占用了w而不能繼續。

小結:

讀者-寫者問題為我們解決復雜的互斥問題提供了思路,核心思想在于設置一個計數器count來記錄當前正在訪問共享文件的讀進程數,用count的值來判斷當前進入的進程是否是第一個/最后一個讀進程,從而跳過部分P指令,實現讀進程不互斥。

在對count變量的檢查和賦值不能一氣呵成時,采用mutex變量來確保count部分被互斥訪問。

在寫進程會饑餓時,引入了w變量來確保可以公平的完成先來先服務。

哲學家進餐問題(避免死鎖)

圓桌上坐著5位哲學家,每兩個哲學家之間擺著一根筷子,桌子的中間是火鍋,哲學家們會思考和干飯。哲學家們在思考時不會影響別人,只有想干飯時,才會拿起左、右各一根筷子(一根一根拿),如果筷子已經在他人手上則需要等待。因為火鍋很燙,哲學家必須需要一雙筷子才能進餐,進餐完畢后,哲學家放下筷子繼續思考。

難點:這個問題中只有互斥關系,沒有同步關系,但是在這個模型中,每個哲學家進程都需要同時持有兩個臨界資源才能開始吃飯。我們可以想到一個很尷尬的情況,那就是每個哲學家都拿了一根筷子,大家都沒有辦法吃飯,但是都在等待別人吃飯然后讓出筷子,這就是死鎖這是臨界資源分配不當導致的,我們要設法避免這種情況發生。

關系分析:

①系統中有5個哲學家進程,5位哲學家與左右鄰居對其之間的筷子的訪問是互斥關系。

②筷子是本模型中的臨界資源,哲學家想要吃飯需要獲取其左右兩根筷子。

我們給哲學家和筷子編號為0~4。顯然,編號為i的哲學家需要編號i和i+1的兩根筷子來吃飯,考慮到邊界,嚴謹的表述是i和(i+1)%5

我們很容易想到一個簡單的寫法:

這種寫法能實現對筷子的互斥訪問,但是不能避免前面提到的死鎖問題。那么該怎么解決呢?

①可以要求奇數號哲學家先拿左手的筷子,偶數號哲學家先拿右手的筷子。如圖所示,以0、1為例,這樣兩位就會在一開始爭搶1號筷子,誰先拿到,另一個就在不占用任何筷子的情況下直接進入阻塞態,這樣就避免了五個人每人占用一根筷子進入阻塞態的死鎖。

以代碼實現的話,在每個哲學家拿筷子之前判斷號碼的奇偶,然后確定P操作的順序即可。

②保證至少有一個哲學家可以一氣呵成的拿到完整的一雙筷子

使用mutex互斥變量,保證至少有一個哲學家可以拿到完整的一雙筷子。

在拿筷子的部分前后加入了mutex的PV操作。當0號哲學家拿筷子時,先P(mutex),之后依次拿起左右的筷子,即使在這過程中發生了進程調度,別的進程也會因為mutex值已經為0被阻塞,不能拿起筷子,直到0號哲學家把筷子拿完,釋放mutex以后,別的哲學家才能拿起筷子。這樣能夠保證,至少第一個開始拿筷子的進程會一氣呵成的拿到一雙筷子,避免死鎖。

但是,這個方法也有一個問題。如圖所示,當0號哲學家拿完一雙筷子開始進餐后,4號哲學家開始拿筷子,因為此時mutex已經釋放,4號哲學家順利執行了P(mutex),且拿起了4號筷子,當想拿起0號筷子時,發現被占用,進入阻塞態。

???? 此時,對于2號哲學家來說,他左右兩側的筷子都是可以使用的,沒有被占用,但是如果他想進食,因為4號哲學家還在占用著mutex并被阻塞,所以他在執行P(mutex)時會被阻塞。明明有臨界資源可以用,但是卻不能訪問,這違背了空閑讓進原則,這種方法的并發度不夠高。

最多允許四個哲學家同時拿起筷子

只要最多四個哲學家同時拿起筷子,就必然有至少一個哲學家可以拿起一雙筷子,避免了死鎖。

為了解決這個問題,我們可以把上個方法中,mutex的初始值設置為4。這樣,在上一情況中,4號哲學家依然會被右手的筷子阻塞,但2號哲學家不會被mutex阻塞,可以正常進食。

同時,在極端情況,即每個哲學家進程拿起一根筷子就被調度的情況中,最后一個進程想要拿起筷子時,會因為mutex已經為0,在P(mutex)步驟中被阻塞,從而在不占用任何筷子的情況下進入阻塞態,這樣就不會發生死鎖。

小結:

哲學家進餐問題的關鍵在于避免死鎖,每個進程都需要持有兩個臨界資源,因此就有了“死鎖”的隱患,想避免死鎖,就要盡量讓進程在不占用臨界資源的情況下進入阻塞態。


感謝您看到這里,如果滿意的話麻煩您點個贊支持一下,個人主頁還有更多內容分享。

個人能力不足,如有錯漏部分還請指出,我會盡快修改。

內容總結自王道計算機考研《操作系統》 和 人民郵電出版社《操作系統導論》

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/45201.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/45201.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/45201.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

解決POST請求中文亂碼問題

解決POST請求中文亂碼問題 1、亂碼原因2、解決方法3、具體步驟 💖The Begin💖點點關注,收藏不迷路💖 在Web開發中,處理POST請求時經常遇到中文亂碼問題,這主要是由于服務器在接收到POST請求的數據后&#x…

物聯網時代的等保測評:保障萬物互聯的安全

隨著物聯網(IoT)技術的飛速發展,我們的生活正逐漸進入一個萬物互聯的新時代。從智能家居到智慧城市,從無人駕駛到農業物聯網,IoT技術正在滲透到我們生活的方方面面。然而,隨著IoT設備數量的激增&#xff0c…

BUG解決:postman可以請求成功,但Python requests請求報403

目錄 問題背景 問題定位 問題解決 問題背景 使用Python的requests庫對接物聯數據的接口之前一直正常運行,昨天突然請求不通了,通過進一步驗證發現凡是使用代碼調用接口就不通,而使用postman就能調通,請求參數啥的都沒變。 接口…

SSL 證書錯誤:如何修復以及錯誤發生的原因

SSL證書可以提升網站的可信度。然而,如果您的SSL證書出現錯誤,您可能會得到一個“不安全”的標簽,這可能會導致訪問者失去對您網站的信任并轉向競爭對手。 本文將介紹SSL證書錯誤的原因及其對用戶的潛在影響。隨后,我們將提供詳細…

MybatisPlus 核心功能

MybatisPlus 核心功能 文章目錄 MybatisPlus 核心功能1. 條件構造器1.1 QueryWrapper1.2 LambdaQueryWrapper(推薦)1.3 UpdateWrapper1.4 LambdaUpdateWrapper 2. 自定義SQL3. Service接口 1. 條件構造器 當涉及到查詢或修改語句時,MybatisP…

界面組件Kendo UI for React 2024 Q2亮點 - 生成式AI集成、設計系統增強

隨著最新的2024年第二季度發布,Kendo UI for React為應用程序開發設定了標準,包括生成式AI集成、增強的設計系統功能和可訪問的數據可視化。新的2024年第二季度版本為應用程序界面提供了人工智能(AI)提示,從設計到代碼的生產力增強、可訪問性…

Java畢業設計 基于SSM vue圖書管理系統小程序 微信小程序

Java畢業設計 基于SSM vue圖書管理系統小程序 微信小程序 SSM 圖書管理系統小程序 功能介紹 用戶 登錄 注冊 首頁 圖片輪播 圖書信息推薦 圖書詳情 贊 踩 評論 收藏 系統公告 公告詳情 用戶信息修改 我的待還 圖書歸還 催還提醒 我的收藏管理 意見反饋 管理員 登錄 個人中心…

絕地求生PUBG奇幻大亂斗怎么玩 奇幻大亂斗什么時候回歸

《絕地求生》(PUBG) 是由韓國開發的一款戰術競技型射擊類沙盒游戲,游戲中我們需要和隊友組隊乘坐飛機跳傘到達一座空島,之后我們需要搜索一切我們可以用到的物資,之后我們于敵人進行對戰,期間不斷躲避毒圈的追擊,最后當…

python(餐廳點餐系統)

全部代碼: meau_lis[[1,"牛排",50],[2,"羊排",80],[3,"大盤雞",50],[4,"火鍋雞",68],[5,"豬大骨",35],[6,"米飯",2],[7,"壽司",5],[8,"大餅",6],[9,"小米粥",1],[10,&…

深入理解MySQL中的EXPLAIN及type列

在MySQL中,EXPLAIN是一個強大的工具,它可以幫助我們理解SQL查詢的執行計劃。通過使用EXPLAIN,我們可以獲取到查詢的詳細信息,包括如何執行查詢,以及查詢的各個部分如何連接在一起。在本篇博客中,我們將重點…

Redis+Caffeine 實現兩級緩存實戰

RedisCaffeine 實現兩級緩存 背景 ? 事情的開始是這樣的,前段時間接了個需求,給公司的商城官網提供一個查詢預計送達時間的接口。接口很簡單,根據請求傳的城市倉庫發貨時間查詢快遞的預計送達時間。因為商城下單就會調用這個接口&#xff…

防火墻安全策略及用戶認證實驗

目錄 一、實驗拓撲 二、實驗要求 三、實驗思路 四、實驗配置 1、配置vlan 2、配置路由器、防火墻IP地址,劃分區域 3、配置安全策略 ?策略一: 策略二: 策略三: 4、配置用戶認證 策略一: 策略二&#xff1a…

視覺SLAM與定位之一前端特征點及匹配

視覺SLAM中的特征點及匹配 參考文章或鏈接特征點性能的評估傳統特征點和描述子(僅特征點或者特征點描述子)傳統描述子 基于深度學習的特征點基于深度學習的描述子基于深度學習的特征點描述子特征匹配 參考文章或鏈接 Image Matching from Handcrafted t…

WebGIS基礎原理

該部分內容與部分插圖、學習框架的主要參考的網站與博主如下(也趁機分享給大家): OSGeo開源WebGIS在線教程:http://webgis.cn/ OSGeo《地理信息系統原理》:https://www.osgeo.cn/gis-tutorial/index.html OSGeo《Pyth…

DSC主備歸檔報錯

先看一個報錯: 2024-07-10 22:12:21.725 [ERROR] database P0000003511 T0000000000000003696 rafil_list_overlap_consecutive_check failed, rfil(DMDATA/data/DSC02/arch/ARCHIVE_LOCAL1_0x57843343_EP1_2024-07-10_20-44-40.log)->next_seq(2901) > nex…

mysql 8.0.37 客戶端在centos7安裝順序

8.0.37安裝客戶端順序為 yum localinstall mysql-community-libs-compat-8.0.37-1.el7.x86_64.rpm #第二步要加 --nodeps --force 參數 rpm -ivh mysql-community-libs-8.0.37-1.el7.x86_64.rpm --nodeps --force rpm -ivh mysql-community-client-plugins-8.0.37-1.el7.x8…

如何用CSS3畫一個三角形?

要用 CSS3 畫一個三角形,可以利用元素的邊框和透明邊框的特性來實現。以下是一個簡單的示例代碼: .triangle {width: 0;height: 0;border-left: 50px solid transparent; /* 左邊框為透明,控制三角形的左斜邊 */border-right: 50px solid tr…

部署Harbor倉庫

本章內容: 安裝docker-ce部署harbor倉庫上傳和拉取 1.安裝docker 1)拉取源碼 yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo 2)安裝docker-ce yum -y install docker-ce 3&#…

【TS】Typescript 的類

TypeScript 是 JavaScript 的一個超集,它添加了可選的靜態類型和基于類的面向對象編程。在 TypeScript 中,類是一種模板,用于創建對象。通過類,你可以封裝對象的屬性(數據)和方法(函數&#xff…

C++入門到進階(圖文詳解,持續更新中)

C入門到進階(圖文詳解,持續更新中) 目錄 C入門到進階(圖文詳解,持續更新中) 數據 數據類型 基本數據類型/內置數據類型 C常用運算符 賦值運算符 關系運算符 邏輯運算符 雜項運算符 數據的本地化…