c++理解多线程与全局变量
C++ understanding multithreading with global variables
我有一个c++程序声明了一些全局变量。之后,它分成几个线程来执行几个任务。这些线程读取和写入这些全局变量中的一些。
如果两个线程读取相同的变量,会有应用程序崩溃吗?或者只有当一个线程将写入另一个线程当前正在读取的变量时,才会出现应用程序崩溃?所以,如果我的第二个问题的答案是肯定的,下面的代码示例能解决这个问题吗?
#include <string>
#include <thread>
#include <mutex>
using namespace std;
mutex m;
string var = "foo";
// function to provide read and write access
// "protected" with mutex
string test(string value = "")
{
m.lock();
if (value == "")
{
m.unlock();
return var;
}
else
{
var = value;
m.unlock();
return "";
}
}
void thread1()
{
// use global variable local
string localVar = test();
}
void thread2()
{
// overwrite global variable
test("bar");
}
void thread3()
{
// use global variable local
string localVar = test();
}
int main()
{
thread t1(thread1);
thread t2(thread2);
thread t3(thread3);
t1.join();
t2.join();
t3.join();
return 0;
}
进一步:这部分是
// ...
if (value == "")
{
m.unlock();
return var;
}
// ...
也thread-save吗?
我的最后一个问题:我的程序目前只使用一个互斥锁来防止两个线程(同一个函数!)同时运行。我不使用互斥锁为我的全局变量。可能是这种"情况"会导致应用程序崩溃(模块:"ntdll.dll")异常代码0xc0000005 ?
提前感谢!
多次读取总是线程安全的。一旦一个线程正在写一个非原子变量var
,而其他线程正在从var
读取,你就处于竞争条件的危险之中。因此,您几乎可以做到这一点,但请使用互斥锁保护(它们是RAII,因此异常安全且更简洁的c++),例如:
#include <mutex>
#include <string>
// ...
std::mutex m;
std::string var = "foo";
// ...
std::string test(const std::string& value = "")
{
std::lock_guard<std::mutex> lock(m);
if (value == "")
{
return var;
}
else
{
var = value;
return "";
}
}
如果两个线程读取相同的变量,会有应用程序崩溃吗?
。从来没有。如果你只从多个线程读取,你总是安全的。
只有当一个线程将写入另一个线程当前正在读取的变量时,才会有应用程序崩溃吗?
不完全是这样,但是可以导致崩溃,这就是代码中发生的事情。从使应用程序从多个线程同时读/写的角度来看,这并不"危险"。最坏的情况是在某些地方得到了垃圾值。这本身不会让你的应用崩溃,但它最终肯定会导致崩溃。问题是当您读取的数据具有原始值以外的含义时(例如整数)。例如,如果您正在读取内存地址(指针),然后尝试访问该地址的内存,但是内存已经被释放,那么您就有麻烦了-这就是代码中发生的情况。字符串的字符已经移动到一个新地址,但是你试图读取旧地址。
<罢工>为了解决这个问题,您应该将整个操作包装在锁中,并且可以为此使用一个临时变量:罢工>
string test(string value = "")
{
m.lock();
if (value == "")
{
string temp = var;
m.unlock();
return temp;
}
else
{
var = value;
m.unlock();
return "";
}
}
正确的答案在Paul的答案中。
如果两个线程读取相同,会有应用程序崩溃吗变量?
不,你可以安全地同时读取全局变量(如果你知道没有人同时写它)。读操作不修改全局值,所以它保持不变,所有的读取器"看到"的是相同的值。
或者只有当一个线程将写入a时才会有应用程序崩溃另一个线程当前正在读取的变量?
通常不会,至少不会因为同时的读和写操作。坠机可能是它的副作用。例如,如果您更新指针值并同时读取它,那么您将尝试访问指针所指向的数据。如果读值无效,很可能导致系统崩溃。
进一步:这部分是
// ... if (value == "") { m.unlock(); return var; } // ...
也thread-save吗?
。互斥锁m
只保护局部变量value
,因为它是局部的,所以不需要保护。但是随后你释放互斥锁并拷贝(读)全局var
变量,而另一个线程可以写它。为了使它线程安全,要么使用std::lock_guard
,然后你就不需要手动锁定/解锁互斥锁。或者将代码更新为:
m.lock();
if (value == "")
{
string ret_val(var);
m.unlock();
return ret_val;
}
正如我之前所写的,是的,作为一个副作用,你的应用程序可能会崩溃。我没有为我的全局变量使用互斥锁。会是这个吗"situation"可能导致应用程序崩溃
简单问题,简单答案:
会有一个应用程序崩溃,如果两个线程正在读取相同的变量?
号只有当一个线程写入另一个线程正在读取的变量时,才会有应用程序崩溃吗?号然而,你真的应该使用锁和互斥锁等来确保你得到预期的程序输出。虽然程序本身不会崩溃,如果一个线程写入一个变量正在被另一个线程读取,您希望读取线程实际读取什么值?之前的值被写入/重写或之后的值?
没有互斥锁就不是线程安全的
建议的解决方案仍然不太正确。
var在互斥锁外被读取,并且可以在那个时候被修改。
这看起来像c++ 11。如果std::string
使用共享字符串(c++ 11禁止),可能会导致读取问题。
在读+写的情况下,如果指针在复制时被修改,则可能发生c0000005(访问冲突)。
- 全局变量 多读取器 一个写入器多线程安全?
- 静态 constexpr 类成员变量对多线程读取是否安全?
- 成员变量在多线程 C++ 时自行更改
- C++多线程程序:变量定义为类成员的隔离错误
- 对全局变量的多线程访问:我应该使用互斥锁吗?
- 多线程处理中的静态成员变量
- C++ 多线程中的锁和条件变量问题
- 我们是否需要对多线程 x32 系统使用 lock 来读取或写入 uint32_t 变量
- 在C++中使用多线程时,是否可以读取半写的、损坏的原始变量?
- C 中的多线程程序:在标志变量上使用Mutex
- C++/Clr 中C++全局实例上的多线程
- 最佳多线程全局变量管理
- 使用C 的多线程应用程序中测量全局时间(壁挂)的最快方法
- SDL 带变量的多线程处理 -- 无法按预期工作
- 如何为多线程应用程序创建全局对象
- 管理多线程应用程序中的共享变量
- 增强多线程和共享变量
- C ++似乎变量与多线程" flush "
- c++理解多线程与全局变量
- 带有全局变量的C++多线程