成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

多線程背景下,讀請求不斷,寫請求有機會執行嗎?怎么分析?

開發 前端
在多線程編程中,讀寫鎖(Read-Write Lock)的機制是否會導致寫請求在持續讀請求下無法執行(即 寫線程饑餓),取決于鎖的具體實現策略和場景特性。

先用代碼測試下題目當中的情況(完整代碼,可以直接復制用來測試,文末抽獎送書,歡迎參與) 

#include <shared_mutex>
#include <thread>
#include <vector>
#include <iostream>
#include <chrono>

std::shared_mutex rw_mutex;
std::string shared_data;

void reader(int id){
    while (true)
    {
        std::shared_lock lock(rw_mutex);
        std::cout << "Reader " << id << " reads: " << shared_data << std::endl;

        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
}

void writer(const std::string& new_data){
    
    while (true)
    {
        std::unique_lock lock(rw_mutex);
        shared_data = new_data;
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
}

int main(){
    std::vector<std::thread> readers;
    for (int i = 0; i < 5; ++i) {
        readers.emplace_back(reader, i);
    }
    std::thread writer_thread(writer, "Updated Data");
    for (auto& t : readers) {
        t.join();
    }
    writer_thread.join();

    getchar();
    return0;
}

VS2022 執行代碼后,觀察控制臺輸出:

ImageImage

讀線程持續打印 “Reader X reads: Updated Data”(初始值為空)。 

寫線程在測試期間未能成功獲取鎖,導致 shared_data 未被更新為 “Updated Data” 

我這里代碼故意在讀處理中加了延時,讀線程長時間持有鎖,然后是 5 個讀線程,可以發現寫請求完全得不到機會來處理。 

這個現象有個專業名詞叫:寫線程饑餓。 

在多線程編程中,讀寫鎖(Read-Write Lock)的機制是否會導致寫請求在持續讀請求下無法執行(即 寫線程饑餓),取決于鎖的具體實現策略和場景特性。以下是逐步分析: 

一、讀寫鎖的基本行為

讀寫鎖的核心規則是 “讀共享,寫獨占”: 

  • 讀鎖(共享鎖):允許多個線程同時讀取資源。
  • 寫鎖(獨占鎖):同一時間僅允許一個線程寫入資源,且寫入時會阻塞所有讀鎖和寫鎖。

因此,當讀鎖持續占用時,寫鎖必須等待所有讀鎖釋放后才能獲取。但具體能否執行需結合鎖的調度策略分析。 

鎖獲取優先級:  

無公平性策略:若讀鎖持續被獲取,寫鎖可能無限等待(饑餓)。  

寫優先策略:當寫鎖請求存在時,后續讀鎖會被阻塞,直到寫鎖完成。  

公平策略:交替服務讀/寫請求,避免單一方饑餓。 

二、寫請求能否執行的場景分析

場景 1:讀寫鎖無公平性策略(常見默認實現)

問題:若讀線程持續獲取讀鎖(無間隙釋放鎖),寫線程可能永遠無法執行。  

示例代碼:  

std::shared_mutex rw_mutex;
void reader() {
    while (true) {
        std::shared_lock lock(rw_mutex); // 持續持有讀鎖
        // 讀操作...
    }
}
void writer() {
    std::unique_lock lock(rw_mutex); // 永遠無法獲取寫鎖
    // 寫操作...
}

結果:寫線程饑餓。 

場景 2:讀寫鎖支持寫優先

策略:當有寫鎖等待時,新讀鎖請求被阻塞,直到寫鎖完成。  

實現方式:維護寫等待標記(如計數器),讀鎖獲取前檢查該標記。  

結果:寫線程最終能獲得鎖,但可能犧牲讀吞吐量。 

場景 3:讀寫鎖支持公平性

策略:通過隊列或時間戳保證讀/寫請求按到達順序交替執行。  

示例:Linux 內核的 rw_semaphore 使用公平隊列。  

結果:寫線程不會饑餓,但并發讀性能下降。 

三、C++標準庫 std::shared_mutex

我們文章開頭的測試出現了寫線程饑餓,那么 std::shared_mutex到底是公平性的還是非公平性的?還是說可以設置呢? 

1. C++ 標準的立場

C++ 標準僅定義 std::shared_mutex 的接口和行為規范(如“讀鎖共享,寫鎖獨占”),但 未規定鎖的獲取策略是否公平。這意味著: 

公平性(如讀/寫鎖的排隊順序、是否避免饑餓)由具體實現決定。 

不同平臺(如 Linux、Windows)或編譯器(如 GCC、Clang、MSVC)可能有不同行為。 

2. 常見實現的行為

Linux( GCC/libstdc++)  

底層通常基于 pthread_rwlock_t,默認采用 讀優先策略(允許新讀請求搶占等待的寫鎖),可能導致 寫線程饑餓。(不同 Linux 發行版或 glibc 版本可能有不同默認行為,需查閱具體文檔) 

示例:若某線程持有讀鎖時,其他讀線程可以繼續獲取讀鎖,而寫線程可能長時間無法獲取鎖。 

Windows( MSVC)  

底層可能使用 SRWLock(Slim Reader/Writer Lock),其特性是:無優先級保障的競爭式獲取,可能但不必然導致寫饑餓。 當鎖釋放時,等待的讀/寫線程通過競爭獲取鎖,不保證先到先得。 

寫線程可能因競爭失敗而饑餓,但實際行為依賴線程調度。 

四、解決方案:避免寫饑餓的設計

1. 選擇支持寫優先的讀寫鎖

手動實現(示例):  

class FairReadWriteLock {
    std::mutex mtx;
    std::condition_variable cv;
    int readers = 0;
    int writers_waiting = 0;
    bool writing = false;
    
public:
    void read_lock(){
        std::unique_lock lock(mtx);
        cv.wait(lock, [this] { 
            return !writing && writers_waiting == 0; // 無寫者或等待的寫者
        });
        readers++;
    }
    void read_unlock(){
        std::unique_lock lock(mtx);
        if (--readers == 0 && writers_waiting > 0) {
            cv.notify_one(); // 喚醒寫者
        }
    }
    void write_lock(){
        std::unique_lock lock(mtx);
        writers_waiting++;
        cv.wait(lock, [this] { 
            return !writing && readers == 0; // 無活動的讀/寫者
        });
        writers_waiting--;
        writing = true;
    }
    void write_unlock(){
        std::unique_lock lock(mtx);
        writing = false;
        cv.notify_all(); // 喚醒所有讀者和寫者
    }
};

效果:當有寫者等待時,新讀者被阻塞,確保寫者最終執行。 

2. 使用操作系統級公平鎖

Linux:通過 pthread_rwlockattr_setkind_np 設置 PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP。  

pthread_rwlock_t rwlock;
pthread_rwlockattr_t attr;
pthread_rwlockattr_init(&attr);
pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP);
pthread_rwlock_init(&rwlock, &attr);

3. 業務層限流

在讀邏輯中插入條件檢查,主動釋放鎖允許寫操作:(此方法依賴線程調度器實現,可能緩解但無法徹底避免饑餓) 

void reader() {
    while (true) {
        {
            std::shared_lock lock(rw_mutex);
            // 讀操作...
        }
        std::this_thread::yield(); // 主動讓出CPU,增加寫者機會
    }
}

六、總結

寫請求能否執行:取決于鎖實現的公平性策略。  

無公平性策略 → 可能饑餓(需業務層干預)。  

寫優先或公平隊列 → 可避免饑餓。   

責任編輯:武曉燕 來源: CppPlayer
相關推薦

2011-12-16 20:37:16

webOS

2020-01-13 14:16:32

區塊鏈應用社交網絡

2011-11-03 09:13:52

UbuntuCanonical移動

2020-07-29 19:07:59

戴爾

2018-05-28 13:31:00

職場阿里巴巴

2025-01-21 00:00:00

HashMap死循環數據損壞

2014-09-09 17:23:54

移動互聯網App市場

2013-01-05 14:57:08

2013手機操作系統Ubuntu

2013-02-25 09:33:38

英特爾移動市場機會

2019-01-07 20:30:48

NoSQLNewSQL數據庫

2012-11-12 09:26:06

.NET多線程

2015-10-22 15:56:27

RFID技術物聯網

2017-09-10 23:37:24

2013-02-27 10:51:36

2015-07-29 15:05:01

2010-05-25 10:19:18

谷歌蘋果

2018-04-11 10:51:25

多線程進程主線程

2021-01-11 11:14:35

微服務架構調用

2011-04-14 13:27:53

Synchronize多線程

2023-11-09 07:23:57

Istio路由分析
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 免费观看一区二区三区毛片 | 伊人伊人伊人 | 九九热视频这里只有精品 | 亚洲成人免费 | 九色91视频| 国产精品视频久久久久久 | 成人在线视频网站 | 超碰在线97国产 | 伊人网综合 | 国产美女福利在线观看 | 中文二区 | 精品国产一区久久 | 日日日干干干 | 国产免费一区二区三区最新6 | 欧美亚洲一区二区三区 | 亚洲精品视频免费观看 | av在线免费播放 | 色婷婷av久久久久久久 | 91电影| 精品免费在线 | 欧美亚洲一区二区三区 | www.99热这里只有精品 | 99精品国产一区二区三区 | av中文在线 | 国产高清视频在线观看 | 国产激情一区二区三区 | 成人欧美一区二区三区黑人孕妇 | 欧美精品在线免费观看 | 91视频国产精品 | 精品不卡 | 9久久精品| 国产午夜av片 | 国产精品久久久久久久久久久久久久 | 国产在线精品一区二区 | 欧美一级欧美三级在线观看 | 隔壁老王国产在线精品 | 久久久国产一区二区三区 | 欧美群妇大交群中文字幕 | 九九在线精品视频 | 久色视频在线观看 | 干干干操操操 |