理解EnterCriticalSection 臨界區

通俗解釋就像上廁所:
門鎖了,就等著,等到別人出來了,進去鎖上,然后該干什么干什么,干完了,把門打開

門沒鎖,就進去,鎖上,然后該干什么干什么,干完了,把門打開

--------------------------------------------------
多線程中用來確保同一時刻只有一個線程操作被保護的數據

InitializeCriticalSection(&cs);//初始化臨界區
EnterCriticalSection(&cs);//進入臨界區
//操作數據
MyMoney*=10;//所有訪問MyMoney變量的程序都需要這樣寫Enter.. Leave...
LeaveCriticalSection(&cs);//離開臨界區
DeleteCriticalSection(&cs);//刪除臨界區

多個線程操作相同的數據時,一般是需要按順序訪問的,否則會引導數據錯亂,無法控制數據,變成隨機變量。為解決這個問題,就需要引入互斥變量,讓每個線程都按順序地訪問變量。這樣就需要使用EnterCriticalSection和LeaveCriticalSection函數。

?

比如說我們定義了一個共享資源dwTime[100],兩個線程ThreadFuncA和ThreadFuncB都對它進行讀寫操作。當我們想要保證 dwTime[100]的操作完整性,即不希望寫到一半的數據被另一個線程讀取,那么用CRITICAL_SECTION來進行線程同步如下:

第一個線程函數:

DWORD ? WINAPI ? ThreadFuncA(LPVOID ? lp)
{
EnterCriticalSection(&cs);
...
// ? 操作dwTime
...
LeaveCriticalSection(&cs);
return ? 0;
}

寫出這個函數之后,很多初學者都會錯誤地以為,此時cs對dwTime進行了鎖定操作,dwTime處于cs的保護之中。一個“自然而然”的想法就是——cs和dwTime一一對應上了。

這么想,就大錯特錯了。dwTime并沒有和任何東西對應,它仍然是任何其它線程都可以訪問的。如果你像如下的方式來寫第二個線程,那么就會有問題:

DWORD ? WINAPI ? ThreadFuncB(LPVOID ? lp)
{
...
// ? 操作dwTime
...
return ? 0;
}

當線程ThreadFuncA執行了EnterCriticalSection(&cs),并開始操作dwTime[100]的時候,線程 ThreadFuncB可能隨時醒過來,也開始操作dwTime[100],這樣,dwTime[100]中的數據就被破壞了。

為了讓CRITICAL_SECTION發揮作用,我們必須在訪問dwTime的任何一個地方都加上 EnterCriticalSection(&cs)和LeaveCriticalSection(&cs)語句。所以,必須按照下面的 方式來寫第二個線程函數:

DWORD ? WINAPI ? ThreadFuncB(LPVOID ? lp)
{
EnterCriticalSection(&cs);
...
// ? 操作dwTime
...
LeaveCriticalSection(&cs);
return ? 0;
}

這樣,當線程ThreadFuncB醒過來時,它遇到的第一個語句是EnterCriticalSection(&cs),這個語句將對cs變量 進行訪問。如果這個時候第一個線程仍然在操作dwTime[100],cs變量中包含的值將告訴第二個線程,已有其它線程占用了cs。因此,第二個線程的 EnterCriticalSection(&cs)語句將不會返回,而處于掛起等待狀態。直到第一個線程執行了 LeaveCriticalSection(&cs),第二個線程的EnterCriticalSection(&cs)語句才會返回, 并且繼續執行下面的操作。

這個過程實際上是通過限制有且只有一個函數進入CriticalSection變量來實現代碼段同步的。簡單地說,對于同一個 CRITICAL_SECTION,當一個線程執行了EnterCriticalSection而沒有執行LeaveCriticalSection的時 候,其它任何一個線程都無法完全執行EnterCriticalSection而不得不處于等待狀態。

再次強調一次,沒有任何資源被“鎖定”,CRITICAL_SECTION這個東東不是針對于資源的,而是針對于不同線程間的代碼段的!我們能夠用它來進 行所謂資源的“鎖定”,其實是因為我們在任何訪問共享資源的地方都加入了EnterCriticalSection和 LeaveCriticalSection語句,使得同一時間只能夠有一個線程的代碼段訪問到該共享資源而已(其它想訪問該資源的代碼段不得不等待)。

這就是使用一個CRITICAL_SECTION時的情況。你應該要知道,它并沒有什么可以同步的資源的“集合”。這個概念不正確。

如果是兩個CRITICAL_SECTION,就以此類推。


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

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

相關文章

Python多線程--UDP聊天器

import socket import threadingdef recv_msg(udp_socket):"""接收數據并顯示"""# 接收數據while True:recv_data udp_socket.recvfrom(1024)print(recv_data)def send_msg(udp_socket, dest_ip, dest_port):"""發送數據"&…

mvc:default-servlet-handler/作用

<mvc:default-servlet-handler/>使用默認的servlet來相應靜態文件&#xff0c;因為在web.xml中使用了DispatcherServlet截獲所有的請求url&#xff0c;而引入<scprit type"text/javascript" src"js/jquery-1.11.0.mim.js"/>的時候&#xff0c;…

java中如何做模糊查詢_到底Java里的模糊查詢語句該怎么寫

該樓層疑似違規已被系統折疊 隱藏此樓查看此樓現在String sql"select * from car where carName like %?%";可以查詢出結果了&#xff0c;但問題又來了&#xff0c;只能查詢出一條結果&#xff0c;代碼如下carDao.java頁面public ArrayList queryAppoint(String car…

vector 、map 、iterator 之學習筆記

由于本人要接手一項C方面 的工作。由于不會C,不過做過JAVA 以及一些web方面的開發&#xff0c;加之時間比較短。所以需要速成&#xff0c;于是學習筆記也基本都是用代碼代替。 //范例資源文件 /****************************************************************************…

redis的密碼驗證,及哨兵的相關配置

背景我們知道&#xff0c;redis默認是不配置密碼的&#xff0c;這就造成只要有redis的IPPort就可以無需驗證&#xff0c;登陸redis。如果恰巧你的redis是開放在公網上的&#xff0c;很容易就被******&#xff0c;獲取你的系統權限&#xff0c;經常被黑去當成了礦機。redis的安全…

tag的使用

tag True while tag:print("level")choice input("level>>>").strip() #作用是暫停 不會一直死循環if choice "quit":break #終止當前循環進入到上一層if choice "quit_all": tag False #不用一層層退出 直接退出整個…

pyecharts對于經緯度_一文帶你掌握Pyecharts地理數據可視化的方法

本文主要介紹了Pyecharts地理數據可視化&#xff0c;分享給大家&#xff0c;具體如下&#xff1a;一、Pyecharts簡介和安裝1. 簡介Echarts 是一個由百度開源的數據可視化&#xff0c;憑借著良好的交互性&#xff0c;精巧的圖表設計&#xff0c;得到了眾多開發者的認可。而 Pyth…

使用Sqlmap對dvwa進行sql注入測試(初級階段)

0.測試準備 1&#xff09;打開Kali虛擬機終端; 2&#xff09;打開靶機OWASP&#xff0c;并通過瀏覽器&#xff0c;輸入IP地址進入dvwa的主頁&#xff0c;然后選擇SQL injection進入SQL注入的測試頁面 1.獲取DVWA的url和cookie 在輸入框中輸入1&#xff0c;顯示有內容&…

什么是軟件生命周期

軟件生命周期又稱為軟件生存周期或系統開發生命周期&#xff0c;是軟件的產生直到報廢的生命周期&#xff0c;周期內有問題定義、可行性分析、總體描述、系統設計、編碼、調試和測試、驗收與運行、維護升級到廢棄等階段&#xff0c;這種按時間分程的思想方法是軟件工程中的一種…

STL中map和string, vector 用法詳解

1. map 用法詳解 std map是STL的一個關聯容器&#xff0c;它提供一對一&#xff08;其中第一個可以稱為關鍵字&#xff0c;每個關鍵字只能在map中出現一次&#xff0c;第二個可能稱為該關鍵字的值&#xff09;的數據處理能力&#xff0c;由于這個特性&#xff0c;它完成有可能…

如果備份還原SecureCRT、Xshell遠程工具遠程

因為有時候電腦操作系統要重新安裝&#xff0c;需要將遠程備份下來。或者要將遠程發給其他同事。一、如何備份還原SecureCRT遠程1、打開options-global options---general---configuration paths找到配置文件保存路徑&#xff0c;如下圖&#xff1a;2、打開C:\Users\NUC\AppDat…

Centos7 下yum安裝mysql

轉載于:https://www.cnblogs.com/nbjjy/p/9023991.html

Python協程--迭代器

0. 實現一個可以迭代的對象 1&#xff09;要想使一個對象實現迭代的功能&#xff0c;須實現__iter__和__next__方法。 2&#xff09;判斷classmate是否是可以迭代的對象&#xff1a; from collections import Iterable isinstance(classmate, Iterable)結果為True則說明是可以…

什么是敏捷開發

什么是敏捷開發&#xff1f; 敏捷開發(Agile Development)是一種以人為核心、迭代、循序漸進的開發方法。 怎么理解呢&#xff1f;首先&#xff0c;我們要理解它不是一門技術&#xff0c;它是一種開發方法&#xff0c;也就是一種軟件開發的流程&#xff0c;它會指導我們用規定的…

May 18:PHP 輸出語句

通過前面的學習了解了php的基本語法&#xff0c;今天向大家簡單介紹php的幾種輸出方式&#xff1a; 1. echo 常用的輸出語句&#xff0c;例如&#xff1a;echo helloworld&#xff01;; 2. print() 輸出語句&#xff0c;有返回值。例如&#xff1a;print(helloworld&#x…

SendMessage、PostMessage原理和源代碼詳解

本文講解SendMessage、PostMessage兩個函數的實現原理&#xff0c;分為三個步驟進行講解&#xff0c;分別適合初級、中級、高級程序員進行理解&#xff0c;三個步驟分別為&#xff1a; 1、SendMessage、PostMessage的運行機制。 2、SendMessage、PostMessage的運行內幕。 3、…

Python協程--實現斐波那契數列(Fibonacci)的幾種方式

1.使用for遍歷list數組 # 使用for遍歷list數組 nums list() a 0 b 1 i 0while i < 10:nums.append(a)a, b b, abi 1for num in nums:print(num)2.使用迭代器完成 class Fibonacci(object):def __init__(self, all_num):self.all_num all_numself.current_num 0sel…

敏捷開發宣言

敏捷開發宣言&#xff1a; 1. 個體和交互勝過過程和工具 2. 可工作的軟件勝過面面俱到的文檔 3. 客戶協作勝過合同談判 4. 響應變化勝過遵循計劃 從上面的宣言可以看出&#xff0c;敏捷開發的核心是人 、協作、時刻可運行的軟件、變化。

java fast math,Java FastMath.signum方法代碼示例

import org.apache.commons.math3.util.FastMath; //導入方法依賴的package包/類/*** {inheritDoc}*/Overrideprotected double doSolve()throws TooManyEvaluationsException,NoBracketingException {double min getMin();double max getMax();// [x1, x2] is the bracketin…

什么是可行性研究

1.并非任何問題都有簡單明顯的解決辦法&#xff0c;事實上&#xff0c;許多問題不可能在預定的系統規模或時間期限之內解決。2.如果問題沒有可行的解&#xff0c;那么花費在這項工程上的任何時間、人力、軟硬件資源和經費&#xff0c;都是無謂的浪費。3.可行性研究的目的&#…