为什么它不是线程安全以及如何获得线程安全?
Why it's not thread safety and how to get it thread safety?
FCGI中有一些函数叫做"getRequestContent()"。它只是获取通过网络浏览器发布的数据。因此,我们的 c++ 应用程序类似于为 Web 客户端服务的守护进程。我想我对不是"线程安全"功能有某种问题:
/**
* Note this is not thread safe due to the static allocation of the
* content_buffer.
*/
std::string getRequestContent(const FCGX_Request &request)
{
char *content_length_str = FCGX_GetParam("CONTENT_LENGTH", request.envp);
unsigned long content_length = STDIN_MAX;
if (content_length_str)
{
content_length = strtol(content_length_str, &content_length_str, 10);
if (*content_length_str)
{
std::cerr << "Can't Parse 'CONTENT_LENGTH='"
<< FCGX_GetParam("CONTENT_LENGTH", request.envp)
<< "'. Consuming stdin up to " << STDIN_MAX << "n";
}
if (content_length > STDIN_MAX)
{
content_length = STDIN_MAX;
}
}
else
{
content_length =
0; // Do not read from stdin if CONTENT_LENGTH is missing
}
char *content_buffer = new char[content_length];
std::cin.read(content_buffer, content_length);
content_length = std::cin.gcount();
do
std::cin.ignore(1024);
while (std::cin.gcount() == 1024);
std::string content(content_buffer, content_length);
delete[] content_buffer;
return content;
}
请解释为什么它不是线程安全代码?我们这里有什么问题?如何获得线程安全?:)
主要问题是,就像评论所说,有一个静态分配的缓冲区。如果两个线程在该缓冲区上同步工作,则很可能会获得竞争条件,因此必须避免这种情况。
这意味着要么修复FCGX_GetParam
(我怀疑这是一个好主意,因为它是第三方库)要么同步对它的访问:
//some common mutex
std::mutex mtx;
std::string getRequestContent(const FCGX_Request &request)
{
std::string content_length_str;
{
lock(mtx); //guard every action on the static buffer with this lock
char *content_length_cptr = FCGX_GetParam("CONTENT_LENGTH", request.envp);
content_length_str = content_length_cptr; //copy the content of the buffer
} //unlock the mutex, you dont work on the buffer hence forth
unsigned long content_length = 0;
if (!content_length_str.empty()) try {
content_length = boost::lexical_cast<unsigned long>(content_length_str);
if (content_length > STDIN_MAX)
{
content_length = STDIN_MAX;
}
}
catch(boost::bad_lexical_cast const&)
{
std::cerr << "Can't Parse 'CONTENT_LENGTH='"
<< content_length_str
<< "'. Consuming stdin up to " << STDIN_MAX << "n";
content_length = STDIN_MAX;
}
// the rest as it was...
}
char * content_length_str = FCGX_GetParam( "CONTENT_LENGTH", request.envp );
这一行可能意味着两件事:
如果函数返回由 alloc/calloc 分配的块,则您正在泄漏内存或者函数使用静态缓冲区。那不是线程安全的。考虑到评论,我猜这是第二种选择。
相关文章:
- 如何将元素添加到数组的线程安全函数?
- C++中的线程安全删除
- 在std::thread中,joinable()然后join()线程安全吗
- 在c++队列中使用pop和visit实现线程安全
- 以线程安全的方式调用"QQuickPaintedItem::updateImage(const QImage&image)"(no QThread)
- 全局变量 多读取器 一个写入器多线程安全?
- 共享队列的线程安全
- boost::文件系统::recursive_directory_iterator多线程安全
- 以线程安全的方式转换 C/C++ 中时区名称字符串的时区偏移量
- 线程安全运算符<<
- 如何使缓存线程安全
- C++线程安全:如果只有一个线程可以写入非原子变量,但多个线程从中读取. 会遇到问题吗?
- 提升精神 V2 Qi 语法线程安全吗?
- asio 链对象线程安全吗?
- 线程安全队列 c++
- 提供对不同类型的数据(建议、代码审查)的线程安全访问的类
- 如何以线程安全的方式更改目录?
- 线程安全的引用计数队列C++
- 析构函数和线程安全
- 适用于大型数组的无复制线程安全环形缓冲区