日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > windows >内容正文

windows

计算机操作系统同步互斥

發(fā)布時間:2024/7/23 windows 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 计算机操作系统同步互斥 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

1 背景

在計算機系統(tǒng)里面, 多道程序設(shè)計是現(xiàn)代操作系統(tǒng)的重要特征, 且并行起到了很大的作用, 所以操作系統(tǒng)抽象出來了線程/進程的概念用來支持多道程序設(shè)計, 同時, 各個進程之間需要進行交互, CPU也需要進行調(diào)度來支持多進程. 多進程會涉及到共享資源訪問的問題, 如果操作系統(tǒng)調(diào)度不當(dāng), 就可能出現(xiàn)饑餓, 死鎖等問題. 以下是獨立進程/線程與合作進程/線程(進程/線程間會有交互, 并共享資源等)的對比:

獨立的進程/線程:

  • 不和其他進程/線程共享資源或狀態(tài)
  • 確定性: 輸入狀態(tài)決定結(jié)果
  • 可重現(xiàn): 能夠重現(xiàn)起始條件, I/O
  • 調(diào)度順序不重要

合作進程/線程:

  • 在多個線程中共享狀態(tài)
  • 不確定性
  • 不可重現(xiàn)

不確定性和不可重現(xiàn)意味著bug可能是間歇性發(fā)生的, 但是計算機/設(shè)備需要合作, 其優(yōu)點如下:

  • 共享資源
  • 一臺電腦, 多個用戶
  • 一個銀行存款余額, 多臺ATM
  • 嵌入式系統(tǒng)(機器人控制: 手臂與手的協(xié)調(diào))
  • 加速
  • I/O操作和計算可以重疊
  • 多處理器 - 將程序分成多個部分并行執(zhí)行
  • 優(yōu)化
  • 將大程序分解成小程序(以編譯為例, gcc會調(diào)用cpp, cc1, cc2, as, ld)
  • 使系統(tǒng)易于擴展

?而我們希望的多進程/線程的運行方式為:

  • 無論多進程/線程的指令序列怎樣交替執(zhí)行, 程序都必須正常工作
  • 多線程程序具有不確定性和不可重現(xiàn)的特點
  • 不經(jīng)過專門設(shè)計, 調(diào)試難度很高
  • 不確定性要求并行程序的正確性
  • 先思考清楚問題, 把程序的行為設(shè)計清楚
  • 切忌急于著手編寫代碼, 碰到問題再調(diào)試

2 一些概念

競態(tài)條件:

?系統(tǒng)缺陷: 結(jié)果依賴于并發(fā)執(zhí)行或者事件的順序/時間

  • 不確定性
  • 不可重現(xiàn)

如何避免競態(tài)條件? 可以讓執(zhí)行指令不被打斷

原子操作:

原子操作是指一次不存在任何中斷或者失敗的執(zhí)行:

  • 該執(zhí)行成功結(jié)束
  • 或者根本沒有執(zhí)行
  • 并且不應(yīng)該發(fā)現(xiàn)任何部分執(zhí)行的狀態(tài)

實際上操作往往不是原子的

  • 有些看上去是原子操作, 實際上不是
  • 連?++這樣的簡單語句, 實際上是由3條指令構(gòu)成的
  • 有時候甚至連單條機器指令都不是原子的

臨界區(qū):

臨界區(qū)是指進程中的一段需要訪問共享資源并且當(dāng)另一個進程處于相應(yīng)代碼區(qū)域時便不會被執(zhí)行的代碼區(qū)域.

互斥:

當(dāng)一個進程處于臨界區(qū)并訪問共享資源時, 沒有其他進程會處于臨界區(qū)并且訪問任何相同的共享資源.

死鎖:

兩個或以上的進程, 在相互等待完成特定任務(wù), 而最終沒法將自身任務(wù)進行下去.

饑餓:

一個可執(zhí)行的進程, 被調(diào)度器持續(xù)忽略, 以至于雖然處于可執(zhí)行狀態(tài)卻不被執(zhí)行.

3 臨界區(qū)

3.1 臨界區(qū)中執(zhí)行的屬性

臨界區(qū)中執(zhí)行需要有一些屬性保證臨界區(qū)的順利執(zhí)行:

  • 互斥: 同一時間臨界區(qū)中最多存在一個線程
  • progress: 如果一個線程想要進入臨界區(qū), 那么它最終會成功(也就是說不會讓一個想要進入臨界區(qū)的線程一直等待, 總會進入的)
  • 有限等待: 如果一個線程 i 處于入口區(qū), 那么在 i 的請求被接受之前, 其他線程進入臨界區(qū)的時間是有限制的(只會等待有限制的時間)
  • 無忙等待(可選): 如果一個進程在等待進入臨界區(qū), 那么在它可以進入之前會被掛起(就是不要用while循環(huán)一直在檢查是否能進入, 會消耗CPU資源)

3.2 三種針對臨界區(qū)屬性的保護方法

3.2.1 禁用硬件中斷

在臨界區(qū)里面進程執(zhí)行是屏蔽中斷的: 沒有中斷, 沒有上下文切換, 因此沒有并發(fā).

  • 硬件將中斷處理延遲到中斷被啟用之后
  • 大多數(shù)現(xiàn)代計算機體系結(jié)構(gòu)都提供指令來完成

進入臨界區(qū)

  • 禁用中斷

離開臨界區(qū)

  • 開啟中斷

利用中斷來確保臨界區(qū)順利執(zhí)行的缺點:

  • 一旦中斷被禁用, 線程就無法被停止
  • 整個系統(tǒng)都會為你停下來
  • 可能導(dǎo)致其他線程處于饑餓狀態(tài)
  • 要是臨界區(qū)可以任意長怎么辦
  • 無法限制相應(yīng)中斷所需的時間(可能存在硬件影響)
  • 在多CPU的情況下, 只禁用一個CPU的中斷無法解決問題?

因此需要小心使用

3.2.2 基于軟件的解決方法

滿足互斥, 但是有時候不滿足progress.

3.2.3 更高級的抽象

更高級的抽象方法是需要一定的基礎(chǔ)的, 這個基礎(chǔ)就是硬件要提供一些原語支持:

  • 比如像中斷禁用, 原子操作指令等
  • 大多數(shù)現(xiàn)代體系結(jié)構(gòu)都這樣

有了上面的基礎(chǔ), 操作系統(tǒng)就可以利用這些硬件支持來提供更高級的編程抽象來簡化多進程/多線程的并行編程:

  • 比如像鎖, 信號量
  • 這些高級的用于并行編程的抽象概念是通過上面說的硬件原語構(gòu)建的

下面用鎖來舉例:

鎖是一個抽象的數(shù)據(jù)結(jié)構(gòu), 也就是上面說的高級的用于并行編程的抽象概念, 具有以下特點:

  • 一個二進制狀態(tài)(鎖定/解鎖), 兩種方法
  • Lock::Acquire() --- 鎖被釋放前一直等待, 然后得到鎖
  • Lock::Release() --- 釋放鎖, 喚醒任何等待的進程

如果使用鎖來處理臨界區(qū)的話, 可以如下:

lock_next_pid->Acquire(); new_pid = next_pid++; lock_next_pid->Release();

這樣就保證了臨界區(qū)的順利執(zhí)行.

那么lock的兩個接口是怎么實現(xiàn)的呢, 前面說過, 是通過現(xiàn)代計算機的體系結(jié)構(gòu)提供的硬件支持, 大索數(shù)現(xiàn)代體系結(jié)構(gòu)都提供特殊的原子操作指令:

  • 通過特殊的內(nèi)存訪問電路
  • 針對單處理器和多處理器

比如硬件提供了以下兩種原子操作指令:

1. Test - and - Set測試和置位

  • 從內(nèi)存中讀取值
  • 測試該值是否為1(然后返回真或假)
  • 該內(nèi)存值置為1
  • 其簡單實現(xiàn)如下:

    boolean TestAndSet(boolean *target) {boolean rv = *target;*target = TRUE;return rv; }

    2. 交換

    • 交換內(nèi)存中的兩個值

    簡單實現(xiàn)如下:

    void Exchange(boolean *a, boolean *b) {boolean temp = *a;*a = *b;*b = temp; }

    有了以上兩種硬件提供的原子操作指令: TestAndSet以及Exchange之后, 我們就可以利用這兩條指令來設(shè)計鎖的Acquire和Release接口了:

    1. 用TestAndSet實現(xiàn)

    class Lock {int value = 0; }Lock::Acquire(){while(TestAndSet(&value)){} }Lock::Release() {value = 0; }

    設(shè)計思路:

    • Acquire: 初始化的時候value為0, 代表沒有其他進程/線程進入臨界區(qū), 這時候Acquire里面調(diào)用TestAndSet返回值是0, 但是value被設(shè)置成了1, 這樣就可以直接退出, 從而進入臨界區(qū)執(zhí)行, 這時候如果其他進程調(diào)用這個lock的Acquire, 這時候value是1了,?TestAndSet返回值是1, value設(shè)置為1, 這樣就會一直在while條件里面循環(huán).(忙等)
    • Release: 把value置為0, 這樣就會讓其他調(diào)用Acquire的線程中TestAndSet的返回值置為0從而退出while循環(huán)從而繼續(xù)執(zhí)行

    方法評價:

    這種方法是忙等, 會占用CPU資源. 可以使用在等待過程中掛起該線程的方式, 并喚醒其他等待進程的方式. 但是這種方式需要上下文切換, 如果預(yù)計等待時間較長的話, 可以選擇這種方式.

    2. 用Exchange實現(xiàn)

    簡單實現(xiàn)如下:

    int lock = 0; //設(shè)置一個全局初始變量 //以下是線程Ti想要進入臨界區(qū)的操作 int key; do {key = 1;while (key == 1)exchange(&lock, &key);//然后執(zhí)行臨界區(qū)代碼lock = 0;//執(zhí)行剩余代碼 }

    設(shè)計思路:

    • 當(dāng)?shù)谝粋€線程想要進入臨界區(qū)之前, 先把key設(shè)置為1, 然后判斷key = 1的話, 就執(zhí)行交換key和lock, 這時lock被置為1, 因為是第一個線程, 所以此時key為0, 退出循環(huán), 執(zhí)行臨界區(qū)代碼.
    • 當(dāng)其他線程在第一個線程執(zhí)行臨界區(qū)代碼過程中想要進入臨界區(qū), 執(zhí)行exchange之后, 因為lock值在有線程在臨界區(qū)執(zhí)行時都會是1, 所以key一直都是1, 也就會一直在while中循環(huán).
    • 在臨界區(qū)線程執(zhí)行完畢后, 會把lock置為0, 讓其他線程進入.?

    優(yōu)缺點:

    • 優(yōu)點: 適用于單處理器或者共享主存的多處理器中任意數(shù)量的進程, 簡單并且容易證明, 可以用于支持多臨界區(qū).
    • 缺點: 忙等待消耗處理器時間, 當(dāng)進程離開臨界區(qū)并且多個進程在等待的時候可能導(dǎo)致饑餓. 死鎖: 如果一個低優(yōu)先級進程擁有臨界區(qū)并且一個高優(yōu)先級進程也需求, 那么高優(yōu)先級進程會獲得處理器并等待臨界區(qū), 最終結(jié)果是高優(yōu)先級進程忙等占用CPU, 低優(yōu)先級進程占用臨界區(qū)卻得不到CPU資源進而無法釋放鎖, 導(dǎo)致兩個進程的臨界區(qū)代碼都無法正常執(zhí)行.

    總結(jié)

    以上是生活随笔為你收集整理的计算机操作系统同步互斥的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。