1. 程式人生 > >C/C++多執行緒、執行緒同步(互斥鎖與訊號量)

C/C++多執行緒、執行緒同步(互斥鎖與訊號量)

參考連結2.中寫的非常好,簡單易懂,上手快,非常好的博文。

使用多執行緒及互斥鎖樣例:

#include <iostream>
#include <windows.h>
using namespace std;

HANDLE hMutex = NULL;//互斥量
//執行緒函式
DWORD WINAPI Fun(LPVOID lpParamter)
{
    for (int i = 0; i < 10; i++)
    {
        //請求一個互斥量鎖
        WaitForSingleObject(hMutex, INFINITE);
        cout << "A Thread Fun Display!" << endl;
        Sleep(100);
        //釋放互斥量鎖
        ReleaseMutex(hMutex);
    }
    return 0L;//表示返回的是long型的0

}

int main()
{
    //建立一個子執行緒
    HANDLE hThread = CreateThread(NULL, 0, Fun, NULL, 0, NULL);
    hMutex = CreateMutex(NULL, FALSE,"screen");
    //關閉執行緒
    CloseHandle(hThread);
    //主執行緒的執行路徑
    for (int i = 0; i < 10; i++)
    {
        //請求獲得一個互斥量鎖
        WaitForSingleObject(hMutex,INFINITE);
        cout << "Main Thread Display!" << endl;
        Sleep(100);
        //釋放互斥量鎖
        ReleaseMutex(hMutex);
    }
    return 0;
}

備註:dwMilliseconds表示千分之一秒,所以 Sleep(1000); 表示暫停1秒。

=================多執行緒及執行緒同步內容=======================

執行緒同步:

執行緒的同步問題。對於一個資源被多個執行緒共用會導致程式的混亂,解決方法是只允許一個執行緒擁有對共享資源的獨佔,這裡我們用互斥量(Mutex)來進行執行緒同步。

互斥鎖和訊號量

“訊號量用在多執行緒多工同步的,一個執行緒完成了某一個動作就通過訊號量告訴別的執行緒,別的執行緒再進行某些動作(大家都在semtake的時候,就阻塞在 哪裡)。而互斥鎖是用在多執行緒多工互斥的,一個執行緒佔用了某一個資源,那麼別的執行緒就無法訪問,直到這個執行緒unlock,其他的執行緒才開始可以利用這 個資源。比如對全域性變數的訪問,有時要加鎖,操作完了,在解鎖。有的時候鎖和訊號量會同時使用的”
也就是說,訊號量不一定是鎖定某一個資源,而是流程上的概念,比如:有A,B兩個執行緒,B執行緒要等A執行緒完成某一任務以後再進行自己下面的步驟,這個任務 並不一定是鎖定某一資源,還可以是進行一些計算或者資料處理之類。而執行緒互斥量則是“鎖住某一資源”的概念,在鎖定期間內,其他執行緒無法對被保護的資料進 行操作。在有些情況下兩者可以互換。

兩者之間的區別:

作用域


訊號量: 程序間或執行緒間(linux僅執行緒間的無名訊號量pthread semaphore)
互斥鎖: 執行緒間

上鎖時 
訊號量: 只要訊號量的value大於0,其他執行緒就可以sem_wait成功,成功後訊號量的value減一。若value值不大於0,則sem_wait使得執行緒阻塞,直到sem_post釋放後value值加一,但是sem_wait返回之前還是會將此value值減一
互斥鎖: 只要被鎖住,其他任何執行緒都不可以訪問被保護的資源

=================建立多執行緒使用的API=======================

HANDLE CreateThread(
    LPSECURITY_ATTRIBUTES lpThreadAttributes,//SD:執行緒安全相關的屬性,常置為NULL
    SIZE_T dwStackSize,//initialstacksize:新執行緒的初始化棧的大小,可設定為0
    LPTHREAD_START_ROUTINE lpStartAddress,//threadfunction:被執行緒執行的回撥函式,也稱為執行緒函式
    LPVOID lpParameter,//threadargument:傳入執行緒函式的引數,不需傳遞引數時為NULL
    DWORD dwCreationFlags,//creationoption:控制執行緒建立的標誌
    LPDWORD lpThreadId//threadidentifier:傳出引數,用於獲得執行緒ID,如果為NULL則不返回執行緒ID
    )

/*
lpThreadAttributes:指向SECURITY_ATTRIBUTES結構的指標,決定返回的控制代碼是否可被子程序繼承,如果為NULL則表示返回的控制代碼不能被子程序繼承。

dwStackSize:設定初始棧的大小,以位元組為單位,如果為0,那麼預設將使用與呼叫該函式的執行緒相同的棧空間大小。
任何情況下,Windows根據需要動態延長堆疊的大小。

lpStartAddress:指向執行緒函式的指標,函式名稱沒有限制,但是必須以下列形式宣告:
DWORD WINAPI 函式名 (LPVOID lpParam) ,格式不正確將無法呼叫成功。

lpParameter:向執行緒函式傳遞的引數,是一個指向結構的指標,不需傳遞引數時,為NULL。

dwCreationFlags:控制執行緒建立的標誌,可取值如下:
(1)CREATE_SUSPENDED(0x00000004):建立一個掛起的執行緒(就緒狀態),直到執行緒被喚醒時才呼叫
(2)0:表示建立後立即啟用。
(3)STACK_SIZE_PARAM_IS_A_RESERVATION(0x00010000):dwStackSize引數指定初始的保留堆疊的大小,
如果STACK_SIZE_PARAM_IS_A_RESERVATION標誌未指定,dwStackSize將會設為系統預留的值

lpThreadId:儲存新執行緒的id

返回值:函式成功,返回執行緒控制代碼,否則返回NULL。如果執行緒建立失敗,可通過GetLastError函式獲得錯誤資訊。


*/

BOOL WINAPI CloseHandle(HANDLE hObject);        //關閉一個被開啟的物件控制代碼
/*可用這個函式關閉建立的執行緒控制代碼,如果函式執行成功則返回true(非0),如果失敗則返回false(0),
如果執行失敗可呼叫GetLastError.函式獲得錯誤資訊。
*/
HANDLE WINAPI CreateMutex(
    LPSECURITY_ATTRIBUTES lpMutexAttributes,        //執行緒安全相關的屬性,常置為NULL
    BOOL                  bInitialOwner,            //建立Mutex時的當前執行緒是否擁有Mutex的所有權
    LPCTSTR               lpName                    //Mutex的名稱
);
/*
MutexAttributes:也是表示安全的結構,與CreateThread中的lpThreadAttributes功能相同,表示決定返回的控制代碼是否可被子程序繼承,如果為NULL則表示返回的控制代碼不能被子程序繼承。
bInitialOwner:表示建立Mutex時的當前執行緒是否擁有Mutex的所有權,若為TRUE則指定為當前的建立執行緒為Mutex物件的所有者,其它執行緒訪問需要先ReleaseMutex
lpName:Mutex的名稱
*/

DWORD WINAPI WaitForSingleObject(
    HANDLE hHandle,                             //要獲取的鎖的控制代碼
    DWORD  dwMilliseconds                           //超時間隔
);

/*
WaitForSingleObject:等待一個指定的物件(如Mutex物件),直到該物件處於非佔用的狀態(如Mutex物件被釋放)或超出設定的時間間隔。除此之外,還有一個與它類似的函式WaitForMultipleObjects,它的作用是等待一個或所有指定的物件,直到所有的物件處於非佔用的狀態,或超出設定的時間間隔。 

hHandle:要等待的指定物件的控制代碼。

dwMilliseconds:超時的間隔,以毫秒為單位;如果dwMilliseconds為非0,則等待直到dwMilliseconds時間間隔用完或物件變為非佔用的狀態,如果dwMilliseconds 為INFINITE則表示無限等待,直到等待的物件處於非佔用的狀態。
*/
BOOL WINAPI ReleaseMutex(HANDLE hMutex);

//說明:釋放所擁有的互斥量鎖物件,hMutex為釋放的互斥量控制代碼

==============視訊處理使用多執行緒===============

#include <opencv2/core/version.hpp>
#include <opencv2/calib3d/calib3d.hpp>
#include <opencv2/opencv.hpp>

using namespace System::Runtime::InteropServices;
using namespace System::IO;
using namespace System::Data;
using namespace System::Drawing;
using namespace System::Drawing::Imaging;
using namespace System::Runtime::Serialization::Formatters::Binary;
using namespace System::Windows::Forms;
using namespace System::Threading;

using namespace FRS;
using namespace FRS::Util;
using namespace DataAngine;

HANDLE hMutex = CreateMutex(NULL,FALSE,NULL);


cv::VideoCapture *cap;
void Show(){
    while (true){
        cv::Mat frame;
        WaitForSingleObject(hMutex, INFINITE);
        cap>>frame;
        ReleaseMutex(hMutex);
        imshow("video", frame);
        cv::waitKey(1000 / cap->get(CV_CAP_PROP_FPS));
    }
}
int main()
{
    FeatureData ^fa = gcnew FeatureData();

    //cap.open(0);
    cap = new cv::VideoCapture();
    cap->open("rtsp://admin:[email protected]:554");

    if (!cap->isOpened())
    {
        std::cout << "open rtsp error" << std::endl;
        return 0;
    }
    Thread ^showThread = gcnew Thread(gcnew ThreadStart(Show));
    showThread->Start();
    
    bool stop = true;
    while (stop)
    {
        cv::Mat frame;
        WaitForSingleObject(hMutex, INFINITE);
        cap>>frame;
        ReleaseMutex(hMutex);
        if (frame.empty()) continue;
        System::GC::Collect();
        
        Thread::Sleep(100);
    }
}


參考:

1.http://www.blogjava.net/fhtdy2004/archive/2009/07/05/285519.html

2.http://www.cnblogs.com/codingmengmeng/p/5913068.html

3.https://www.cnblogs.com/pkjplayer/p/6653197.html

相關推薦

C/C++執行執行同步互斥訊號

參考連結2.中寫的非常好,簡單易懂,上手快,非常好的博文。使用多執行緒及互斥鎖樣例:#include <iostream> #include <windows.h> using namespace std; HANDLE hMutex = NULL;

執行同步互斥訊號的作用區別

“訊號量用在多執行緒多工同步的,一個執行緒完成了某一個動作就通過訊號量告訴別的執行緒,別的執行緒再進行某些動作(大家都在semtake的時候,就阻塞在 哪裡)。而互斥鎖是用在多執行緒多工互斥的,一個執行緒佔用了某一個資源,那麼別的執行緒就無法訪問,直到這個執行緒unloc

圖解程序執行互斥訊號-看完不懂你來打我

![](https://img2020.cnblogs.com/other/1815316/202009/1815316-20200906085125268-309001835.png) 在上學的時候,老師講到程序與執行緒的時候可能是這樣講的: * 程序是一個具有一定獨立功能的程式在一個數據集上的一次動態

執行同步互斥訊號

同步概念: 當多個執行緒共享相同的一塊記憶體時(實際上在一個程序的各個執行緒之間,除了棧區的資料之外,其他的資料這幾個縣城之間都是相互共享的),需要確保每個執行緒看到一致的資料檢視。也就是說,這些執行緒在對資料進行操作時,應該是同步的,也就是說當一個執行緒正在操作一個數據時,其他執行緒無法同時對

Linux執行程式設計---執行同步互斥條件變數訊號和讀寫

本篇博文轉自http://zhangxiaoya.github.io/2015/05/15/multi-thread-of-c-program-language-on-linux/ Linux下提供了多種方式來處理執行緒同步,最常用的是互斥鎖、條件變數、訊號量和讀寫鎖。  下面是思維導

python之執行訊號

執行緒鎖(互斥鎖Mutex) 一個程序下可以啟動多個執行緒,多個執行緒共享父程序的記憶體空間,也就意味著每個執行緒可以訪問同一份資料,此時,如果2個執行緒同時要修改同一份資料,會出現什麼狀況?就會可能存在同時取出了一個數據進行操作,然後存回去,這樣就會丟失一次操作。所以用鎖,在修改之前鎖上資料,

守護進執行互斥訊號,佇列,死遞迴

守護程序: from multiprocessing import Process import os,time,random def task(): print('%s is running' %os.getpid()) time.sleep(2)

利用XShell上傳下載文件使用szrz命令,超實用!

rec pre xshell 命令 方法 font 所有 shel 不包含 借助XShell,使用linux命令sz可以很方便的將服務器上的文件下載到本地,使用rz命令則是把本地文件上傳到服務器。 其中,對於sz和rz的理解與記憶我用了如下的方法(很多時候容

C++ 執行框架 2:Mutex 互斥和 Sem 訊號

互斥和訊號量是多執行緒程式設計的兩個基礎,其原理就不詳細說了,大家去看看作業系統的書或者網上查查吧。 對於互斥的實現,無論什麼作業系統都離不開三個步驟 1.初始化互斥鎖 2.鎖操作 3.解鎖操作 對於不同的系統只是實現的函式有一些不同而已,但是功能其實都大同小異,在

【Linux C 執行程式設計】互斥條件變數

一、互斥鎖互斥量從本質上說就是一把鎖, 提供對共享資源的保護訪問。  1. 初始化:  在Linux下, 執行緒的互斥量資料型別是pthread_mutex_t. 在使用前, 要對它進行初始化:  對於靜態分配的互斥量, 可以把它設定為PTHREAD_MUTEX_INITIA

CUDA執行執行執行處理器流處理器網格概念的深入理解

一.與CUDA相關的幾個概念:thread,block,grid,warp,sp,sm。 sp: 最基本的處理單元,streaming processor  最後具體的指令和任務都是在sp上處理的。GPU進行平行計算,也就是很多個sp同時做處理 sm:多個sp加上其他的一些資源組成一個

Python工——程序執行協程對比

在這條生產線上多招些工人,一起來做剪子,這樣效率是成倍増長,即單程序 多執行緒方式 老闆發現這條生產線上的工人不是越多越好,因為一條生產線的資源以及材料畢竟有限,所以老闆又花了些財力物力購置了另外一條生產線,然後再招些工人這樣效率又再一步提高了,即多程序 多執行緒方式 老闆發現,現在已經有了很多條生產

《瘋狂Java講義第4版》-----第16章【執行控制執行執行同步

控制執行緒 join執行緒 等那個執行緒做完後,當前執行緒再做! import java.lang.Thread; public class MyThread extends Thread{ public MyThread(String name){ super(

【java執行】守護執行執行停止volatile的深入瞭解

文章目錄 執行緒的優雅停止 守護執行緒 volatile關鍵字 執行緒的優雅停止       在多執行緒的操作之中如果要啟動多執

Java之執行執行

多執行緒 執行緒:執行緒是程序中的一個執行單元,負責當前程序中程式的執行,一個程序中至少一個執行緒(main),但是可以有多個執行緒的,則這個程式稱為多執行緒程式。每一個執行緒執行不同的任務,多執行緒程式並不能提高程式的執行速度,可以提高程式的執行效率。 CPU處理可以分為

python執行非同步post請求指令碼,可以設定持續執行時間執行時間間隔

#coding=utf8 ''' random.randint(a, b):用於生成一個指定範圍內的整數。 其中引數a是下限,引數b是上限,生成的隨機數n: a <= n <= b random.choice(sequence):從序列中獲取一個隨機元素 引數

Java執行執行的生命週期和狀態控制

一、執行緒的生命週期 執行緒狀態轉換圖: 1、新建狀態 用new關鍵字和Thread類或其子類建立一個執行緒物件後,該執行緒物件就處於新生狀態。處於新生狀態的執行緒有自己的記憶體空間,通過呼叫start方法進入就緒狀態(runnable)。 注意:不能對已經啟動的執行緒再次呼叫star

深入理解併發程式設計 -- 執行底層執行原理執行狀態

併發程式設計 -- 多執行緒底層執行原理、執行緒狀態 作者 : Stanley 羅昊 多執行緒 -- 併發程式設計(一) : https://www.cnblogs.com/StanleyBlogs/p/10890906.html 【轉載請註明出處和署名,謝謝!】 多執行緒底層執行原理 說道底層執行

【SSH網上商城專案實戰15】執行定時器同步首頁資料類似於部落格定期更新排名

  轉自:https://blog.csdn.net/eson_15/article/details/51387378   上一節我們做完了首頁UI介面,但是有個問題:如果我在後臺添加了一個商品,那麼我必須重啟一下伺服器才能重新同步後臺資料,然後重新整理首頁才能同步資

執行互斥條件變數例項理解

互斥鎖: 初始化程序鎖: int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr); 其中 mutex 為鎖號 attr為屬性 摧毀互