1. 程式人生 > >作業系統清華向勇陳渝版筆記(九) 同步協同多道程式設計和併發問題,同步互斥,死鎖,臨界區

作業系統清華向勇陳渝版筆記(九) 同步協同多道程式設計和併發問題,同步互斥,死鎖,臨界區

前篇在此:

正文

9-1 同步互斥、臨界區、死鎖、互斥概念等等

多個程序會互動,對共享資源的訪問。處理不當就會飢餓,死鎖。

獨立的執行緒:不和其他執行緒共享資源或狀態,不互動,所以具有確定性(輸入狀態決定結果),可重現(能重現起始條件),I/O,排程順序不重要
合作的執行緒:在多個執行緒中共享狀態,不確定性,不可重現
不確定性和不可重現意味著BUG可能是間歇性發生的

為什麼要合作?
共享資源(嵌入式系統);
加速,效率高(I/O操作和計算可以重疊,拆分小任務,流水,並行,多處理器);
模組化:大程式分解成小程式,使系統易於擴充套件

存在的問題——>舉例:
這裡寫圖片描述


這裡寫圖片描述

希望是
無論多個執行緒的指令序列怎麼交替,程式都必須正常工作,除錯難度很高;
不確定性要求並行程式的正確性,一定更要預先思考。
Race condition 競態條件
結果依賴於併發執行的時間點 順序/時間

怎麼避免?如何不讓指令被打斷?
atomic operation原子操作
指一次不存在任何中斷或者失敗的執行,要麼成功done要麼沒執行
實際操作往往不是原子的,甚至單個機器指令都不一定是原子的。
對記憶體的load store是原子的,但++ 、–都不是

臨界區critical section:
程序中訪問共享資源的程式碼區域,且當另一個程序處於相應程式碼區域時便不會執行。

互斥mutual exclusion:
任一時刻只能有一個程序進入臨界區訪問。當一個程序處於臨界區並訪問共享資源時,沒有其他程序會處於臨界區,並訪問任何相同的共享資源。

死鎖Dead lock
多個程序相互等待完成特定任務,而最終沒法繼續自身任務

飢餓starvation:
一個可執行的程序長期等待執行,被排程器持續忽略。

可以留便籤,但還是做不到,因為上下文切換不知道何時會發生。
便籤上打不同的標籤→不同標籤的Note+不同程式碼的執行緒/程序
一個while 一個if
busy-waiting 當A等待DO nothing時浪費了CPU的時間,忙等待。
而且有不對稱性

以買麵包bread為例:

假設有一些鎖
breadlock.acquire(): -----enter the critical section 在鎖被釋放前一直等待,然後獲得鎖
if(no bread)
{buy bread;}
lock.release():-----exit the critical section 解鎖並喚醒任何等待中的鎖
release and acquire都要是原子操作,如果兩個程序同時發現了一個被釋放了的鎖,那麼只有一個能獲得

9-2 臨界區和三種滿足效能的方法

臨界區的特點:

  • 互斥
  • progress前進,如果一個執行緒想要進入臨界區,不會一直死等,總能成功
  • 優先等待,如果一個執行緒i處於入口區,那麼i的請求被接受之前,其他執行緒進入臨界區的時間是有限制的。否則,飢餓。是對progress的補充
  • 無忙等待:儘量不要忙等,如果程序一直等待進入臨界區,那麼在它可以進入之前會被掛起。(可以不滿足)

三種方法:禁用硬體中斷,基於軟體,更高階的抽象

(1)禁用硬體中斷:
沒有中斷,就沒有上下文切換,沒有併發。減少不確定性。進入臨界區禁用中斷,退出時再開啟。
問題:
一旦禁用中斷,執行緒無法停止
整個系統都會停下來,I/O啥的都沒用了,其他執行緒可能會飢餓 影響效率
臨界區要是太長咋整?無法限制響應中斷所需的時間,可能有硬體影響。一般都用於短的臨界區時間。
如果兩個CPU並行的話,一個CPU只能遮蔽自身,另一個仍可能產生中斷。

(2)基於軟體的方式

這裡寫圖片描述

共享變數初始化

int turn=0;         //初始是Ti進入臨界區
對Thread Ti,有:
do{
    while(turn!=i);     //  busy waiting
    critical section
    turn=j;                 //after exit turn=j
    reminder section
}while (1);

Ti在退出臨界區後做其他的事情去了,Tj想繼續執行,但必須等待Ti處理臨界區

必須是一種交替迴圈。
改進,用陣列flag

flag[i]==1 程序i想進入臨界區執行
int flag[2];
flag[0]=flag[1]=0;
do{
while(flag[j]==1) ;  //初始flag都是0,沒有滿足互斥
flag[i]==1;   //先請求
critical section
flag[i]=0;
remainder section
}while (1)

如果先flag[i]=1while迴圈,可能死鎖

滿足程序Pi and Pj之間互斥的正解:

use two shared data items
int  turn; // who ‘s turn to enter the critical section
bollean flag[];  //whether the process is ready to enter
PETERSON演算法
do{
flag[i] = TURE;
turn=j;
while(flag[j]&&turn==j ) ;
 CRITICAL SECTION
flag[i]=FLASE;
    REMAINDER SECTION
} while(TURE);

對N個程序,Eisenberg and Mcguire’s algorirhm

這裡寫圖片描述
程序i之前的先進入了i再進入,i之後的等i先進入

Bakery演算法
N個程序的臨界區 排號,只有一個視窗
進入前,程序接受一個數字,數字最小的進入臨界區。如果Pi和Pj
得到相同的數字,比較i,j的大小,小的進入。編號方案總是按照列舉的增加順序生成數字。

問題:
複雜;需要共享資料項
耗資源;需要忙等待,浪費CPU時間
沒有硬體保證的情況下無真正的軟體解決方法;load store必須要是原子操作

(3) 基於硬體原子操作的高層抽象實現
硬體提供了一些原語,用原子操作直接實現進退臨界區
鎖是一個抽象的資料結構,獲得鎖就是進入臨界區的實現過程
lock_next_pid->acquire();
new_pid=next_pid++ ;
lock_next_pid->release();

大多數現代體系結構都提供特殊的原子操作指令
(1) test-and-set 測試和置位
從記憶體中讀值,判斷是否為1並返回,同時設定記憶體值為1
(2) exchange 交換 輸入兩個記憶體單元,交換其值並返回
這兩條如果有一條可以是原子指令,就可以完成

這裡寫圖片描述

lock::release(){value=0;}
可以支援N個程序的操作且是一樣的,都很簡潔
改進:讓它不忙等
當它等待其他事件時,可以睡眠/阻塞

class lock{ int value = 0; waitqueue q;}
lock::acquire(){
while (test-and-set(value)){
add this TCB to wait queen q;
schedule();}
}
lock::release(){
value=0;
remove one thread t from q;
wakeup(t);
}

如果臨界區短,開銷小於上下文切換的開銷,直接忙等,否則要引入WAITING和wakeup

int lock=0;
to process Ti that want to enter the critical section
int key;
do{
key=1;
while(key==1)exchange(lock,key);   //when key!=1 swap out of
critical section  //at that time key=0 lock=1
    lock=0;
remainder section
}

實現簡單,易擴充套件到多臨界區,開銷小,適用於單處理器或共享主存的多處理器中任意數量的程序 廣泛使用
缺點: 還是有忙等,浪費時間;
搶LOCK隨機可能某個一直搶不到,當程序離開臨界區,且多個程序在等待時可能導致飢餓;
也許死鎖,一個低優先順序的程序擁有臨界區,一個高優先順序的 程序也需求,那麼高優先順序程序忙等,佔用cpu,低優先順序的不能釋放Lock,要通過優先順序反轉來解決。

總結:

用鎖來解決互斥問題,鎖是高層程式設計抽象,需要一定硬體支援
常用三種:禁用中斷(僅可單處理器),軟體方法(複雜),原子操作指令(單處理器或多處理器都可以)
可選的實現內容:有忙等待,無忙等待(程序睡眠)

這裡寫圖片描述

相關推薦

作業系統清華筆記 同步協同多道程式設計併發問題同步互斥臨界

前篇在此: 正文 9-1 同步互斥、臨界區、死鎖、互斥概念等等 多個程序會互動,對共享資源的訪問。處理不當就會飢餓,死鎖。 獨立的執行緒:不和其他執行緒共享資源或狀態,不互動,所以具有確定性(輸入狀態決定結果),可重現(能重現起始條件

Android 學習之《第一行程式碼》第二 筆記探究碎片

一、碎片 1. 碎片是什麼: 碎片(Fragment)是一種可以嵌入在活動當中的UI片段,能讓程式更加合理和充分地利用大螢幕的空間。(可以理解成迷你型活動) 2. 簡單用法: 在一個活動當中新增兩個碎片,並讓這兩個碎片平分活動空間。 1.)效果圖(沒錢買平板,CPU不支援

java 併發程式設計學習筆記之 基礎框架搭建併發模擬工具程式碼

                                基礎框架搭建和併發模擬工具,程式碼 (1)基礎框架搭建 (2)併發模擬 (3)CountDownLatch  通常用來 保證 幾個執行緒執行完成之後,再執行其他的程式碼 Semaphore

小甲魚《零基礎學習Python》課後筆記:了不起的分支迴圈2

測試題 0.下面的迴圈會列印多少次 for i in range(0, 10, 2):   print('I love FishC')   5次。range(0, 10, 2)得到[0,2,4,6,8],總共5次。 1. 下面的迴圈會列印多少次“I Lov

C語言學習筆記—— 函式、遞迴指標

一、函式1、一個簡單的函式示例函式是完成特定任務的獨立程式程式碼單元。#include <stdio.h> void printStar();//宣告函式原型,函式原型會指明函式的型別和函式接受的引數。前面的void是函式型別,表明函式沒有返回值 #define

《Qt5 開發與實例第三》學習筆記

nal inf lin exc ken right item vbo ott 1 // 3.4 基本布局(QLayout) 2 //dialog.h 3 #ifndef DIALOG_H 4 #define DIALOG_H 5 6 #incl

Spring實戰第四筆記-2裝配Bean

一、Spring配置的可選方案     建立應用物件之間協作關係的行為通常稱為裝配(wiring),這也是依賴注入(DI)的本質。Spring裝配容器最常見有三種方法:   1、在XML中進行顯式配置;   2、在Java中進行顯式配置(JavaConfig);   3、隱式的bean發現機制和自動裝

python基礎教程第三)學習筆記

第九章 魔法方法、特性和迭代器 9.1 如果你使用的不是python3 在Python 2.2中,Python物件的工作方式有了很大的變化。這種變化帶來了多個方面的影響。這些影響對Python程式設計新手來說大都不重要,但有一點需要注意:即便你使用的是較新的Python 2版本,有些功能(如特性

Android 學習之《第一行程式碼》第二 筆記探究碎片

一個簡易版的新聞應用 同時相容手機和平板的應用程式 一、佈局 news_content_frag.xml額我的程式碼裡面是news_content_fragment.xml,圖片打錯了 二、程式碼編寫 1. 實體類(News.java) //新聞實體類 pub

Effective Java 第三筆記目錄

《Effective Java, Third Edition》一書英文版已經出版,這本書的第二版想必很多人都讀過,號稱Java四大名著之一,不過第二版2009年出版,到現在已經將近8年的時間,但隨著Java 6,7,8,甚至9的釋出,Java語言發生了深刻的變化。 讀書筆記 第1章 介紹 (Intro

mysql學習筆記—— MySQL內連接外連接

聚集函數 信息 _id left tro 做了 學習 作用 group MySQL內連接(inner join on) MySQL的內連接使用inner join on,它的效果跟使用where是一樣的,如果聯結的是兩個表,那麽需要左右的條件或者說字段是

數據結構學習筆記 樹的創建遍歷

一個 後序遍歷 for -1 堆棧 nor ext cnblogs 復制 創建(先序創建和根據先序和中序進行創建)和遍歷(先序遍歷、中序遍歷、後序遍歷、非遞歸堆棧遍歷、層次遍歷):    package tree; public class XianCreateTree

IDEA使用筆記——小齒輪的顯示隱藏Autoscroll from Source

當前 筆記 快捷鍵 什麽 編輯 osc .com log 文件 在玩快捷鍵的時候,不清楚自己操作了什麽,突然間發現——能直接定位到當前可編輯文件的哪個小齒輪,不見了,找了一會也沒弄出來,從網上搜索吧!也沒看到對應的方法,後來自己耐下心來復盤自己的操作,終於發現了,顯示或隱藏

TypeScript學習筆記:裝飾器Decorators

標註 時裝 als cal () 操作 enume 筆記 文檔 裝飾器簡介 裝飾器(Decorators)為我們在類的聲明及成員上通過元編程語法添加標註提供了一種方式。 需要註意的是:裝飾器是一項實驗性特性,在未來的版本中可能會發生改變。 若要啟用實驗性的裝飾器特性

webots自學筆記彈簧與阻尼添加

fec ada -1 pri val src 分享 cit 文章 原創文章,來自“博客園,_阿龍clliu” http://www.cnblogs.com/clliu/,轉載請註明原文章出處。 先說明一下,暑假提前到研究生老

如鵬網學習筆記JavaScript

計算機編程 lean 有效 拼接字符串 {} efault 含義 函數重載 cas JavaScript筆記 一、JavaScript簡介   1,JavaScript是一種計算機編程語言,可以像等其他編程語言那樣定義變量,執行循環等。   2,JavaScript代碼主

Python學習筆記

port 驗證方式 模塊 install name 第三方模塊 rom pip private 一、Python模塊的引入   import sys #可以通過模塊名以及import關鍵字導入模塊 二、if __name__ == "__main__"   當Python在

深度學習筆記感受野計算

lds 時有 輸入 計算 ret name %d have imsi 1 感受野的概念   在卷積神經網絡中,感受野的定義是 卷積神經網絡每一層輸出的特征圖(feature map)上的像素點在原始圖像上映射的區域大小。一般感受野大小是目標大小的兩倍左右最合適!      

java學習筆記:Java 流(Stream)、文件(File)IO

用戶輸入 public 文件內容 輸出流 out 單個 java 我們 ready Java 的控制臺輸入由 System.in 完成。 為了獲得一個綁定到控制臺的字符流,你可以把 System.in 包裝在一個 BufferedReader 對象中來創建一個字符流。需要i

學習筆記——數據庫存儲結構:頁、聚集索引、非聚集索引

分享 style end 宋體 blog lec storage rop cas 1、頁 SQL Server用8KB 的頁來存儲數據,並且在SQL Server裏磁盤 I/O 操作在頁級執行。也就是說,SQL Server 讀取或寫入所有數據頁。頁有不同的類型,像