python實現 進程同步與互斥 讀者-寫者問題 讀者優先 操作系統

題目描述

解決讀者-寫者問題,僅要求解決讀者優先的情況。
提示:創建一個控制檯進程,此進程包含 n 個線程。用這 n 個線程來表示 n 個讀者或寫
者。每個線程按相應測試數據文件的要求進行讀寫操作。

讀者-寫者問題的讀寫操作限制:

1)寫-寫互斥,即不能有兩個寫者同時進行寫操作。
2)讀-寫互斥,即不能同時有一個線程在讀,而另一個線程在寫。
3)讀-讀允許,即可以有一個或多個讀者在讀。

讀者優先的附加限制:

如果一個讀者申請進行讀操作時已有另一個讀者正在進行讀操
作,則該讀者可直接開始讀操作。但任何寫者必須等到沒有讀者時才能開始寫操作。

運行結果顯示要求:

要求在每個線程創建、發出讀寫操作申請、開始讀寫操作和結束讀寫操作時分別顯示一行提示信息,以確定所有處理都遵守相應的讀寫操作限制。

測試數據文件包括 n 行測試數據,分別描述創建的 n 個線程是讀者還是寫者,以及讀寫操作的開始時間和持續時間。每行測試數據包括四個字段,各個字段間用空格分隔。第一字段爲一個正整數,表示線程序號。第二字段表示相應線程角色,R 表示讀者,W 表示寫者。第三字段爲一個正數,表示讀寫操作的開始時間:線程創建後,延遲相應時間(單位爲秒)後發出對共享資源的讀寫申請。第四字段爲一個正數,表示讀寫操作的持續時間。當線程讀寫申請成功後,開始對共享資源的讀寫操作,該操作持續相應時間後結束,並釋放共享資源。

測試數據隨機生成,爲簡化起見,假設每個線程只執行一次讀或寫操作,之後運行結束。

下面是一個測試數據文件的例子:
線程序號 角色 何時開始讀寫 讀寫持續時間
1 R 3 5
2 R 4 5
3 W 5 2
4 R 10 3
5 W 11 3
6 R 13 4
…… …… ……

輸入的形式和輸入值的範圍

測試數據使用文件來保存,在我的程序中命名爲“input.txt”。測試數據文件包括 n 行測試數據,分別描述創建的n個線程是讀者還是寫者,以及讀寫操作的開始時間和持續時間。每行測試數據包括四個字段,各個字段間用空格分隔。第一字段爲一個正整數,表示線程序號。第二字段表示相應線程角色,R 表示讀者,W 表示寫者。第三字段爲一個正數,表示讀寫操作的開始時間:線程創建後,延遲相應時間(單位爲秒)後發出對共享資源的讀寫申請。第四字段爲一個正數,表示讀寫操作的持續時間。

輸入文件 input.txt

在這裏插入圖片描述

輸出結果

在這裏插入圖片描述

主要包含包

(1)threading模塊
threading模塊是在低級別_thread模塊上構建的的高級別線程接口。繼承_thread功能,而_thread模塊是提供處理多進程(也稱輕量級繼承或任務)的基本單元,多進程控制特點是共享全局數據空間.簡單鎖(也稱互斥或二進制信號量)可實現進程同步。
python中線程屬於內核級別,即由操作系統調度(如單線程一旦遇到IO就會被迫交出CPU執行權限,切換到其他線程運行).

(2)Thread類
線程類表示單獨控制運行的線程活動.有兩種建立線程的方式:
• 直接使用Thread類;(本文使用)
• 重構run()方法.

(3)Semaphore類
Semaphore 在內部管理着一個計數器。調用 acquire() 會使這個計數器 -1,release() 則是+1.計數器的值永遠不會小於 0,當計數器到 0 時,再調用 acquire() 就會阻塞,直到其他線程來調用release()
(4)time類
用於獲取當前時間,精確到秒,從而與最開始時間相減來獲得時間點

程序流程圖

在這裏插入圖片描述

各模塊間層次

在這裏插入圖片描述
讀者優先的特點是當讀者進行讀時,後續的寫者必須等待,直到所有的讀者均離開後,寫者纔可進入。
讀者優先問題的關鍵互斥問題是解決“寫者與寫者”和“寫者與第一個讀者”的互斥問題,爲此引入互斥信號量Wmutex。爲了記錄誰是第一個讀者,用一個全局整型變量Rcount做一個計數器。而在解決問題的過程中,由於使用了全局變量Rcount,該變量又是一個臨界資源,對於他的訪問仍需互斥進行,所以需要一個互斥信號量Rmutex。

  1. reader函數
    用於讀者的操作。最開始創建後sleep到開始時間,然後進入等待隊列請求讀操作。請求到之後如果Rcount=0(自己是第一個讀者)則把寫者的信號量申請,不讓寫者進行寫操作,然後Rcount+1,然後釋放Rmutex(讓後續讀進程可以一起申請讀操作)。最關鍵的部分就是Rcount來記錄第一個讀者,實現與寫者的互斥,而這通過互斥信號量Rmutex來修來Rcount.

  2. writer函數
    用於寫者的操作,最開始創建後sleep到開始時間,然後進入等待隊列請求寫操作。然後申請Wmutex信號量,申請到了就可以進行寫,最後再釋放。

  3. 四個list
    idx = [] 存取線程序號
    rwlist = [] 存取線程類型
    start_time = [] 存取線程開始時間
    continue_time = [] 存取線程持續時間

  4. 線程啓動函數

  5. 主函數
    在這裏插入圖片描述

再來一個圖理解

在這裏插入圖片描述

需要的環境

1.安裝python3
2.確保有time threading 兩個模塊(沒有則在命令行運行pip install [模塊名])
3.運行python Reader_first.py
4.也可以使用jupyter打開Reader_first.ipynb 可以看到相關輸出
5.測試數據在input.txt中修改

代碼

import time
import threading
from threading import Semaphore

Wmutex = Semaphore(1)
Rmutex = Semaphore(1)
Rcount = 0

def reader(i,sleept,start,start_sleep):
    time.sleep(start_sleep)
    print('時間點  '+str(int(time.strftime('%S'))-start)+'  reader  '+str(i)+'  waiting to read\n', end='')
    Rmutex.acquire()
    global Rcount
    if Rcount == 0:
        Wmutex.acquire()
    Rcount += 1
    Rmutex.release()
    print('時間點  '+str(int(time.strftime('%S'))-start)+'  reader  '+str(i)+'  reading\n', end='')
    time.sleep(sleept)
    print('時間點  '+str(int(time.strftime('%S'))-start)+'  reader  '+str(i)+'  finish reading\n', end='')
    Rmutex.acquire()
    Rcount -= 1
    if Rcount == 0:
        Wmutex.release()
    Rmutex.release()

def writer(i,sleept,start,start_sleep):
    time.sleep(start_sleep)
    now = int(time.strftime('%S'))
    print('時間點  '+str(int(time.strftime('%S'))-start)+'  writer  '+str(i)+'  waiting to write\n', end='')
    Wmutex.acquire()
    print('時間點  '+str(int(time.strftime('%S'))-start)+'  writer  '+str(i)+'  writing\n', end='')
    time.sleep(sleept)
    print('時間點  '+str(int(time.strftime('%S'))-start)+'  writer  '+str(i)+'  finish writing\n', end='')
    Wmutex.release()


if __name__ == '__main__':
    idx = [] 
    rwlist = []
    start_time = []
    continue_time = []
    with open('input.txt','r') as f:
        data = f.readlines()
        for x in data:
            x = x.split()
            idx.append(int(x[0]))
            rwlist.append(x[1])
            start_time.append(int(x[2]))
            continue_time.append(int(x[3]))
    start = int(time.strftime('%S'))
    print('時間點  '+str(start-start)+'  所有線程開始啓動\n', end='')
    for i in range(len(rwlist)):
        print('時間點  '+str(int(time.strftime('%S'))-start)+'  線程  '+str(idx[i])+'  set up\n', end='')
        if rwlist[i] == 'R':
            t = threading.Thread(target=reader, args=(idx[i],continue_time[i],start,start_time[i]))
            t.start()
        else:
            t = threading.Thread(target=writer, args=(idx[i],continue_time[i],start,start_time[i]))
            t.start()

最後 使用python寫操作系統實驗只需要幾十行代碼 比起用java或者c語言寫上百行 不快樂嗎

給出參考博客

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章