线程安全的向量和字符串容器?
我发布了上一个问题 “使用 std 时的 Seg 错误: :嵌入式 Linux 平台上的字符串”,我在那里得到了一些非常有用的建议。从那时起我就离开了其他项目,最近又开始关注这个问题。
重申一下,我仅限于使用 arm-linux 交叉编译器(版本 2.95.2),因为这是嵌入式平台供应商提供和支持的。我知道这个问题可能是因为 stdlib 非常旧,并且线程不是特别安全。
问题是,每当我在多个线程中使用 STL 容器时,我都会遇到分段错误。下面的代码将始终出现 seg 错误,除非我在容器声明周围使用 pthread_mutex_lock 和作用域运算符(如其他帖子中所示)。
在我的应用程序中使用这种方法是不可行的,因为我将容器传递给不同的方法和类。我理想地想解决这个问题,或者找到合适的替代方案。我尝试过STLPort和SGI的标准模板库,结果相同。我只能假设,因为它们是由非常旧的 gcc 链接的,所以它们无法解决问题。
有人有任何可能的建议或解决方案吗?或者也许您可以建议我可以将矢量(和字符串)的实现放入我的代码中?
预先感谢您的任何指导。
#include <stdio.h>
#include <vector>
#include <list>
#include <string>
using namespace std;
/////////////////////////////////////////////////////////////////////////////
class TestSeg
{
static pthread_mutex_t _logLock;
public:
TestSeg()
{
}
~TestSeg()
{
}
static void* TestThread( void *arg )
{
int i = 0;
while ( i++ < 10000 )
{
printf( "%d\n", i );
WriteBad( "Function" );
}
pthread_exit( NULL );
}
static void WriteBad( const char* sFunction )
{
//pthread_mutex_lock( &_logLock );
//{
printf( "%s\n", sFunction );
string sKiller; // <----------------------------------Bad
//list<char> killer; // <----------------------------------Bad
//vector<char> killer; // <----------------------------------Bad
//}
//pthread_mutex_unlock( &_logLock );
return;
}
void RunTest()
{
int threads = 100;
pthread_t _rx_thread[threads];
for ( int i = 0 ; i < threads ; i++ )
{
pthread_create( &_rx_thread[i], NULL, TestThread, NULL );
}
for ( int i = 0 ; i < threads ; i++ )
{
pthread_join( _rx_thread[i], NULL );
}
}
};
pthread_mutex_t TestSeg::_logLock = PTHREAD_MUTEX_INITIALIZER;
int main( int argc, char *argv[] )
{
TestSeg seg;
seg.RunTest();
pthread_exit( NULL );
}
I posted a previous question "Seg Fault when using std::string on an embedded Linux platform" where I got some very useful advise. I have been away on other projects since then and have recently returned to looking at this issue.
To reiterate, I am restricted to using the arm-linux cross compiler (version 2.95.2) as this is what is supplied and supported by the embedded platform vendor. I understand that the issue is likely because the stdlib is very old, and not particularly thread safe.
The problem is that whenever I use the STL containers in multiple threads, I end up with a segmentation fault. The code below will consistently seg fault unless I use pthread_mutex_lock and scope operators around the container declarations (as in other post).
It is not feasible to use this approach in my application as I pass the containers around to different methods and classes. I would ideally like to solve this problem, or find a suitable alternative. I have tried STLPort and SGI's Standard Template Library with the same results. I can only assume that because they are being linked by the very old gcc, they cannot solve the problem.
Does anyone have any possible recommendations or solutions? Or perhaps you can suggest an implementation of vector (and string) that I can drop into my code?
Thanks in advance for any guidance.
#include <stdio.h>
#include <vector>
#include <list>
#include <string>
using namespace std;
/////////////////////////////////////////////////////////////////////////////
class TestSeg
{
static pthread_mutex_t _logLock;
public:
TestSeg()
{
}
~TestSeg()
{
}
static void* TestThread( void *arg )
{
int i = 0;
while ( i++ < 10000 )
{
printf( "%d\n", i );
WriteBad( "Function" );
}
pthread_exit( NULL );
}
static void WriteBad( const char* sFunction )
{
//pthread_mutex_lock( &_logLock );
//{
printf( "%s\n", sFunction );
string sKiller; // <----------------------------------Bad
//list<char> killer; // <----------------------------------Bad
//vector<char> killer; // <----------------------------------Bad
//}
//pthread_mutex_unlock( &_logLock );
return;
}
void RunTest()
{
int threads = 100;
pthread_t _rx_thread[threads];
for ( int i = 0 ; i < threads ; i++ )
{
pthread_create( &_rx_thread[i], NULL, TestThread, NULL );
}
for ( int i = 0 ; i < threads ; i++ )
{
pthread_join( _rx_thread[i], NULL );
}
}
};
pthread_mutex_t TestSeg::_logLock = PTHREAD_MUTEX_INITIALIZER;
int main( int argc, char *argv[] )
{
TestSeg seg;
seg.RunTest();
pthread_exit( NULL );
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
问题不在于容器,而在于您的代码。
完全没有必要使容器本身线程安全,因为您首先需要的是类似事务的语义。
例如,为了演示,我们假设您有一个
vector
的线程安全实现。if (!vec.empty())
vec.clear();
foo = vec.front();< /code>
这会导致未定义的行为。
问题在于,让容器上的每个操作都是线程安全的几乎毫无意义,因为您仍然需要能够连续锁定容器本身以进行多个操作。因此,您会锁定各种操作,然后再次锁定每个操作?
正如我所说:完全没有必要。
The issue is not with the containers, it's with your code.
It is completely unnecessary to make the containers themselves threadsafe, because what you need, first and foremost, is transaction-like semantics.
Let's assume, for the sake of demonstration, that you have a threadsafe implementation of
vector
, for example.if (!vec.empty())
vec.clear();
foo = vec.front();
This leads to undefined behavior.
The issue is that having each operation on the container threadsafe is pretty much pointless because you are still required to be able to lock the container itself for several operations in a row. Therefore you would lock for your various operations, and then lock again on each and every operation ?
As I said: completely unnecessary.
您的部分疑问可能会在另一个线程中得到解答。 C++的设计,包括标准库,受到很多因素的影响。效率是一个反复出现的主题。线程安全机制通常与效率目标相矛盾。图书馆的年龄并不是真正的问题。
对于您的情况,您可以将 STL 矢量包装在您自己的矢量类中(您可以考虑使用 装饰器),包含锁定机制并提供围绕访问的锁定/解锁逻辑。
Part of your query might be answered in another thread. The design of C++, including the standard library, is influenced by many factors. Efficiency is a repeated theme. Thread safety mechanisms often are at odds with an objective of efficiency. The age of the library is not really the issue.
For your situation, you may be able to wrap the STL vector in your own vector class (you might consider a Decorator) that contains the locking mechanism and provides the lock/unlock logic around accesses.