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