![](/img/trans.png)
[英]Is it possible to compile boost::recursive_mutex statically in C++ Builder
[英]Why boost::recursive_mutex is not working as expected?
我有一個自定義類,該類使用增強互斥鎖和此類鎖(僅相關部分):
template<class T> class FFTBuf
{
public:
FFTBuf();
[...]
void lock();
void unlock();
private:
T *_dst;
int _siglen;
int _processed_sums;
int _expected_sums;
int _assigned_sources;
bool _written;
boost::recursive_mutex _mut;
boost::unique_lock<boost::recursive_mutex> _lock;
};
template<class T> FFTBuf<T>::FFTBuf() : _dst(NULL), _siglen(0),
_expected_sums(1), _processed_sums(0), _assigned_sources(0),
_written(false), _lock(_mut, boost::defer_lock_t())
{
}
template<class T> void FFTBuf<T>::lock()
{
std::cerr << "Locking" << std::endl;
_lock.lock();
std::cerr << "Locked" << std::endl;
}
template<class T> void FFTBuf<T>::unlock()
{
std::cerr << "Unlocking" << std::endl;
_lock.unlock();
}
如果我嘗試從同一線程中多次鎖定對象,則會出現異常(lock_error):
#include "fft_buf.hpp"
int main( void ) {
FFTBuf<int> b( 256 );
b.lock();
b.lock();
b.unlock();
b.unlock();
return 0;
}
這是輸出:
sb@dex $ ./src/test
Locking
Locked
Locking
terminate called after throwing an instance of 'boost::lock_error'
what(): boost::lock_error
zsh: abort ./src/test
為什么會這樣呢? 我對某些概念的理解不正確嗎?
顧名思義,互斥鎖是recursive
但鎖不是。
就是說,您這里有一個設計問題。 最好不要從外部訪問鎖定操作。
class SynchronizedInt
{
public:
explicit SynchronizedInt(int i = 0): mData(i) {}
int get() const
{
lock_type lock(mMutex);
toolbox::ignore_unused_variable_warning(lock);
return mData;
}
void set(int i)
{
lock_type lock(mMutex);
toolbox::ignore_unused_variable_warning(lock);
mData = i;
}
private:
typedef boost::recursive_mutex mutex_type;
typedef boost::unique_lock<mutex_type> lock_type;
int mData;
mutable mutex_type mMutex;
};
recursive_mutex
要點是允許在給定線程中進行鏈鎖定,如果您在某些情況下具有相互調用的復雜操作,則可能會發生這種情況。
例如,讓我們添加調整get:
int SynchronizedInt::UnitializedValue = -1;
int SynchronizedInt::get() const
{
lock_type lock(mMutex);
if (mData == UnitializedValue) this->fetchFromCache();
return mData;
}
void SynchronizedInt::fetchFromCache()
{
this->set(this->fetchFromCacheImpl());
}
問題出在哪里?
get
獲取mMutex
的鎖定 fetchFromCache
調用set
set
獲取鎖的嘗試... 如果我們沒有recursive_mutex
,這將失敗。
該鎖不應屬於受保護資源,而應屬於調用方,因為您有一個線程調用方。 他們必須使用不同的unique_lock。
unique_lock的目的是使用RAII鎖定和釋放互斥鎖,因此您不必顯式調用解鎖。
在方法體內聲明unique_lock時,它將屬於調用線程堆棧。
因此,更正確的用法是:
#include <boost/thread/recursive_mutex.hpp>
#include <iostream>
template<class T>
class FFTBuf
{
public :
FFTBuf()
{
}
// this can be called by any thread
void exemple() const
{
boost::recursive_mutex::scoped_lock lock( mut );
std::cerr << "Locked" << std::endl;
// we are safe here
std::cout << "exemple" << std::endl ;
std::cerr << "Unlocking ( by RAII)" << std::endl;
}
// this is mutable to allow lock of const FFTBuf
mutable boost::recursive_mutex mut;
};
int main( void )
{
FFTBuf< int > b ;
{
boost::recursive_mutex::scoped_lock lock1( b.mut );
std::cerr << "Locking 1" << std::endl;
// here the mutex is locked 1 times
{
boost::recursive_mutex::scoped_lock lock2( b.mut );
std::cerr << "Locking 2" << std::endl;
// here the mutex is locked 2 times
std::cerr << "Auto UnLocking 2 ( by RAII) " << std::endl;
}
b.exemple();
// here the mutex is locked 1 times
std::cerr << "Auto UnLocking 1 ( by RAII) " << std::endl;
}
return 0;
}
請注意const方法互斥量上的可變項。
Boost互斥鎖類型具有scoped_lock typedef,這是很好的unique_lock類型。
嘗試這個:
template<class T> void FFTBuf<T>::lock()
{
std::cerr << "Locking" << std::endl;
_mut.lock();
std::cerr << "Locked" << std::endl;
}
template<class T> void FFTBuf<T>::unlock()
{
std::cerr << "Unlocking" << std::endl;
_mut.unlock();
}
您兩次使用了unique_lock _lock
的同一實例,這是一個問題。 您要么必須直接使用遞歸互斥的方法lock()和unock(),要么使用兩個不同的unique_lock實例,例如_lock
和_lock_2
更新資料
我想補充一點,您的類具有公共方法lock()
和unlock()
,從我的角度看,在實際程序中,這是一個壞主意。 在真實程序中將unique_lock作為類的成員也常常是一個壞主意。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.