柚子快報邀請碼778899分享:QT的互斥量和信號量
柚子快報邀請碼778899分享:QT的互斥量和信號量
文章目錄
一、mutex互斥量1、mutex2、相關(guān)成員函數(shù)
二、semaphore信號量1、信號量2、成員函數(shù)
三、Linux內(nèi)核中的互斥鎖、讀寫鎖、自旋鎖、信號量四、QT簡單日志類代碼
一、mutex互斥量
1、mutex
目的是保護(hù)對象、數(shù)據(jù)結(jié)構(gòu)或代碼段,以便一次只有一個線程可以訪問它。
QMutex mutex;
int number = 6;
void method1()
{
mutex.lock();
number *= 5;
number /= 4;
mutex.unlock();
}
void method2()
{
mutex.lock();
number *= 3;
number /= 2;
mutex.unlock();
}
2、相關(guān)成員函數(shù)
QMutex::QMutex(QMutex::RecursionMode mode)
//構(gòu)造一個新的互斥對象?;コ怄i是在未鎖定狀態(tài)下創(chuàng)建的。
//如果模式是QMutex::Recursive,則線程可以多次鎖定同一個互斥對象,
//并且在進(jìn)行相應(yīng)數(shù)量的unlock()調(diào)用之前,該互斥對象不會被解鎖。
//否則,線程可能只鎖定一次互斥對象。默認(rèn)值為QMutex::NonRecursive。
//遞歸互斥量比非遞歸互斥量慢,占用的內(nèi)存也更多。
bool QMutex::isRecursive() const
//如果這個互斥量為遞歸返回true.
void QMutex::lock()
//鎖定互斥對象。如果另一個線程鎖定了互斥鎖,那么這個調(diào)用將被阻塞,直到該線程將其解鎖。
//如果該互斥對象是遞歸互斥對象,則允許在同一線程的同一互斥對象上多次調(diào)用該函數(shù)。
//如果這個互斥對象是非遞歸互斥對象,那么當(dāng)互斥對象被遞歸鎖定時,這個函數(shù)將死鎖定。
bool QMutex::try_lock()
//嘗試鎖定互斥對象。如果已獲得鎖,此函數(shù)將返回true;否則返回false。
//提供此功能是為了與標(biāo)準(zhǔn)庫概念Lockable兼容。它相當(dāng)于tryLock()。
bool QMutex::tryLock(int timeout = 0)
//嘗試鎖定互斥對象。如果已獲得鎖,此函數(shù)將返回true;否則返回false。
//如果另一個線程鎖定了互斥鎖,則此函數(shù)最多會等待超時毫秒,以便互斥鎖可用。
template
//嘗試鎖定互斥對象。如果已獲得鎖,此函數(shù)將返回true;否則返回false。
//如果另一個線程鎖定了互斥鎖,此函數(shù)將等待duration時間,以使互斥鎖可用。
//注意:傳遞一個負(fù)的持續(xù)時間作為持續(xù)時間相當(dāng)于調(diào)用try_lock()。此行為與tryLock()不同。
template
//嘗試鎖定互斥對象。如果已獲得鎖,此函數(shù)將返回true;否則返回false。
//如果另一個線程鎖定了互斥鎖,此函數(shù)將等待timepoint時間,以使互斥鎖可用。
//注意:傳遞一個timepoint作為持續(xù)時間相當(dāng)于調(diào)用try_lock()。此行為與tryLock()不同。
以上三個方法
//如果獲得了鎖,則必須使用unlock()解鎖互斥鎖,然后另一個線程才能成功鎖定它。
//如果該互斥對象是遞歸互斥對象,則允許在同一線程的同一互斥對象上多次調(diào)用該函數(shù)。
//如果這個互斥鎖是非遞歸互斥鎖,那么當(dāng)試圖遞歸鎖定互斥鎖時,這個函數(shù)總是返回false。
void QMutex::unlock()
//解鎖互斥鎖。試圖解鎖與鎖定互斥鎖的線程不同的線程中的互斥鎖會導(dǎo)致錯誤。
//解鎖未鎖定的互斥對象會導(dǎo)致未定義的行為。
二、semaphore信號量
1、信號量
信號量是互斥鎖的一種推廣。信號量通常用于保護(hù)一定數(shù)量的相同資源。信號量支持兩種基本的操作,acquire() 和 release()。**acquire(n)**嘗試獲取n個資源,如果沒有那么多可用資源,那么調(diào)用將被阻止,直到可以獲取到n個資源;release(n) 釋放n個資源。
QSemaphore sem(5); // sem.available() == 5
sem.acquire(3); // sem.available() == 2
sem.acquire(2); // sem.available() == 0
sem.release(5); // sem.available() == 5
sem.release(5); // sem.available() == 10,此時資源數(shù)超過初始值
sem.tryAcquire(1); // sem.available() == 9, returns true
sem.tryAcquire(250); // sem.available() == 9, returns false
2、成員函數(shù)
QSemaphore::QSemaphore(int n = 0)
//創(chuàng)建新的信號量并且初始化資源的數(shù)量,資源視為n,默認(rèn)為0;
void QSemaphore::acquire(int n = 1)
//嘗試獲取信號量保護(hù)的n個資源。如果n>available(),則此調(diào)用將阻塞,直到有足夠的資源可用為止。
int QSemaphore::available() const
//返回信號量當(dāng)前可用的資源數(shù)。這個數(shù)字永遠(yuǎn)不能是負(fù)數(shù)。
void QSemaphore::release(int n = 1)
//釋放n個信號量保護(hù)的資源
bool QSemaphore::tryAcquire(int n = 1)
//嘗試獲取n個信號量保護(hù)的資源,如果獲取到返回為true,
//如果 available() < n,則立即返回false,不會調(diào)用任何資源
bool QSemaphore::tryAcquire(int n, int timeout)
//嘗試獲取n個信號量保護(hù)的資源,如果獲取到返回為true,
//如果available()<n,則此調(diào)用最多將等待超時毫秒,以便資源變?yōu)榭捎谩?/p>
//注意:傳遞一個負(fù)數(shù)作為超時相當(dāng)于調(diào)用acquire(),即如果超時為負(fù)數(shù),此函數(shù)將永遠(yuǎn)等待資源可用。
三、Linux內(nèi)核中的互斥鎖、讀寫鎖、自旋鎖、信號量
1、互斥鎖(mutex) 是最常用的鎖,它可以保護(hù)共享資源,使得在某個時刻只有一個線程或進(jìn)程可以訪問它。讀寫鎖(rwlock)則可以同時允許多個線程或進(jìn)程讀取共享資源,但只允許一個線程或進(jìn)程寫入它。自旋鎖(spinlock)可以用來保護(hù)共享資源,使得在某個時刻只有一個線程或進(jìn)程可以訪問它,但它會使線程或進(jìn)程“自旋”,直到獲得鎖為止。最后,信號量(semaphore)可以用來控制對共享資源的訪問,以保證其他線程或進(jìn)程可以安全地訪問它們。
2、讀寫鎖(rwlock) 是一種用于控制多線程訪問共享資源的同步機(jī)制。當(dāng)一個線程需要讀取共享資源時,可以獲取讀取鎖,這樣其他線程就可以同時讀取該資源,而不會引發(fā)沖突。當(dāng)一個線程需要寫入共享資源時,可以獲取寫入鎖,這樣其他線程就不能訪問該資源,從而保證數(shù)據(jù)的完整性和一致性。
3、自旋鎖(spinlock) 是一種簡單而有效的用于解決多線程同步問題的鎖。它是一種排他鎖,可以在多線程環(huán)境下保護(hù)共享資源,以防止多個線程同時對該資源進(jìn)行訪問。自旋鎖的基本原理是,當(dāng)一個線程試圖獲取鎖時,它會不斷嘗試獲取鎖,直到成功為止。在這期間,線程不會進(jìn)入休眠狀態(tài),而是一直處于忙等待(busy-waiting)狀態(tài),這也就是自旋鎖的由來。
4、信號量(semaphore) 是一種常用的同步機(jī)制,它可以用來控制多個線程對共享資源的訪問。它有助于確保同一時間只有一個線程能夠訪問共享資源,從而避免資源沖突和競爭。信號量是一種整數(shù)計數(shù)器,用于跟蹤可用資源的數(shù)量。當(dāng)一個線程需要訪問共享資源時,它首先必須獲取信號量,這會將信號量的計數(shù)器減少1,而當(dāng)它完成訪問共享資源后,它必須釋放信號量,以便其他線程也可以訪問共享資源。 更多詳細(xì)介紹
四、QT簡單日志類代碼
1、頭文件
#ifndef LOG_H
#define LOG_H
#include
#include
#include
#include
#include
#include
#include
/***************************************
* 說明:日志功能的單線程實現(xiàn)
* 作者:caokexiang
* 時間:20240522
******************************************/
class QSimpleLog : public QThread
{
Q_OBJECT
public:
QSimpleLog(QString const& fileName);
public:
/***************************************
* 說明: 將記錄寫入日志文件(寫入中文需要提前使用QString::fromLocal8Bit轉(zhuǎn)變字符格式)
* 參數(shù): msg:待寫入的信息
* 作者:caokexiang
* 時間:20240522
******************************************/
void write(const QString& msg);
virtual void run();
private:
QString const fileName; // 文件名
QList
QMutex m_mutex; //對m_msg進(jìn)行線程安全保護(hù)的互斥信號量
QSemaphore m_synSem; //同步信號量,當(dāng)消息隊列未進(jìn)入時,線程處于阻塞狀態(tài),可以避免while一直死循環(huán)
};
#endif
2、源文件
#include "QSimpleLog.h"
QSimpleLog::QSimpleLog(QString const &fileName) : m_synSem(0), fileName(fileName){//初始化信號量,初始資源為0
}
void QSimpleLog::write(const QString& msg)
{
m_mutex.lock();
QString currentDateTime = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss ddd");
QString message = QString("[%1]: %2").arg(currentDateTime).arg(msg);
m_msg.push_back(message);
m_mutex.unlock();
m_synSem.release(); //資源數(shù)增加1
}
void QSimpleLog::run()
{
while (true){
m_synSem.acquire();
m_mutex.lock();
if (m_msg.isEmpty()){
continue;
}
QString message = m_msg.front();
m_msg.pop_front();
QFile file(fileName);
file.open(QIODevice::WriteOnly | QIODevice::Append);
QTextStream text_stream(&file);
text_stream << message << "\r\n";
file.flush();
file.close();
m_mutex.unlock();
}
}
柚子快報邀請碼778899分享:QT的互斥量和信號量
參考鏈接
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。
轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。