并发多线程12windows临界区、其他各种mutex互斥量

第十二节 windows临界区、其他各种mutex互斥量

 

一和二、windows临界区
Windows临界区,同一个线程是可以重复进入的,但是进入的次数与离开的次数必须相等。
C++互斥量则不允许同一个线程重复加锁。

windows临界区是在windows编程中的内容,了解一下即可,效果几乎可以等同于c++11的mutex
包含#include <windows.h>
windows中的临界区同mutex一样,可以保护一个代码段。但windows的临界区可以进入多次,离开多次,但是进入的次数与离开的次数必须相等,不会引起程序报异常出错

#include <iostream>
#include <thread>
#include <list>
#include <mutex>
#include <Windows.h>

#define __WINDOWSJQ_

using namespace std;

class A
{
public:
    // 把收到的消息传入队列
    void inMsgRecvQueue()
    {
        for (size_t i = 0; i < 1000; ++i)
        {
            cout << "收到消息,并放入队列 " << i << endl;

#ifdef  __WINDOWSJQ_
            EnterCriticalSection(&my_winsec);    //    进入临界区
            //EnterCriticalSection(&my_winsec);    //    可以再次进入临界区,程序不会出错
            msgRecvQueue.push_back(i);
            LeaveCriticalSection(&my_winsec);    //    离开临界区
            //LeaveCriticalSection(&my_winsec);    //    如果进入两次,必须离开两次不会报错
#elif
            my_mutex.lock();
            msgRecvQueue.push_back(i);
            my_mutex.unlock();
#endif //  __WINDOWSJQ_
        }

        cout << "消息入队结束" << endl;
    }

    // 从队列中取出消息
    void outMsgRecvQueue()
    {
        for (size_t i = 0; i < 1000; ++i)
        {
#ifdef  __WINDOWSJQ_
            EnterCriticalSection(&my_winsec);    //    进入临界区
            if (!msgRecvQueue.empty())
            {
                // 队列不为空
                int num = msgRecvQueue.front();
                cout << "从消息队列中取出 " << num << endl;
                msgRecvQueue.pop_front();
            }
            else
            {
                // 消息队列为空
                cout << "消息队列为空 " << endl;
            }
            LeaveCriticalSection(&my_winsec);    //    离开临界区
#elif
            my_mutex.lock();
            if (!msgRecvQueue.empty())
            {
                // 队列不为空
                int num = msgRecvQueue.front();
                cout << "从消息队列中取出 " << num << endl;
                msgRecvQueue.pop_front();
                my_mutex.unlock();
            }
            else
            {
                // 消息队列为空
                cout << "消息队列为空 " << endl;
                my_mutex.unlock();
            }
#endif //  __WINDOWSJQ_
        }

        cout << "消息出队结束" << endl;
    }

    A()
    {
#ifdef __WINDOWSJQ_
        InitializeCriticalSection(&my_winsec);    //    用临界区之前要初始化
#endif // __WINDOWSJQ_

    }

private:
    list<int> msgRecvQueue;
    mutex my_mutex;

#ifdef __WINDOWSJQ_
    CRITICAL_SECTION my_winsec;    //    windows中的临界区,非常类似C++11中的mutex
#endif // __WINDOWSJQ_

};

int main()
{
    A myobj;
    thread    myInMsgObj(&A::inMsgRecvQueue, &myobj);
    thread    myOutMsgObj(&A::outMsgRecvQueue, &myobj);
    myInMsgObj.join();
    myOutMsgObj.join();

    getchar();
    return 0;
}

三、自动析构技术
C++:lock_guard防止忘了释放信号量,自动释放
windows:可以写个类自动释放临界区:

class CWinLock {
public:
    CWinLock(CRITICAL_SECTION *pCritmp)
    {
        my_winsec =pCritmp;
        EnterCriticalSection(my_winsec);
    }
    ~CWinLock()
    {
        LeaveCriticalSection(my_winsec)
    };
private:
    CRITICAL_SECTION *my_winsec;
};

四、递归独占互斥量 std::recursive_mutex
std::mutex 独占式互斥量

std::recursive_mutex:允许在同一个线程中同一个互斥量多次被 lock() ,(但是递归加锁的次数是有限制的,太多可能会报异常),效率要比mutex低。

如果你真的用了 recursive_mutex 要考虑代码是否有优化空间,如果能调用一次 lock()就不要调用多次。

 

原文链接:https://blog.csdn.net/qq_38231713/article/details/106093490

原文链接: https://www.cnblogs.com/gk520/p/16646707.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    并发多线程12windows临界区、其他各种mutex互斥量

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/404280

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年4月25日 下午4:26
下一篇 2023年4月25日 下午4:27

相关推荐