带C+的螺纹安全+;并通过引用传递 我想确认我对线程的理解,并在C++中传递引用。以下函数是线程安全的吗 QString sA = "hello"; QString sB = "world"; bool someFlag = AreStringsEqual(sA,sB); ... bool AreStringsEqual(QString const &stringA, QString const &stringB) { if(stringA == stringB) { return true; } return false; }

带C+的螺纹安全+;并通过引用传递 我想确认我对线程的理解,并在C++中传递引用。以下函数是线程安全的吗 QString sA = "hello"; QString sB = "world"; bool someFlag = AreStringsEqual(sA,sB); ... bool AreStringsEqual(QString const &stringA, QString const &stringB) { if(stringA == stringB) { return true; } return false; },c++,thread-safety,C++,Thread Safety,我认为它是线程安全的。我希望有人能证实我的思维过程,或者告诉我我不知道我在说什么:) 进程内存中有两个sA和sB副本。一个集合在Thread1的堆栈上创建,第二个集合在Thread2的堆栈上创建。因为我们是通过引用传递的,所以每个线程在内存中只需要一组sA和sB来执行函数调用 如果改为按值传递,则在某个时间点,进程内存中可能有多达四个sA和sB副本(每个线程有两个集合),其中两个线程都在函数调用中交换处理器控制权 在任何情况下,这里都不共享内存,因此该函数是线程安全的 抱歉,如果这个问题非常

我认为它是线程安全的。我希望有人能证实我的思维过程,或者告诉我我不知道我在说什么:)

  • 进程内存中有两个sA和sB副本。一个集合在Thread1的堆栈上创建,第二个集合在Thread2的堆栈上创建。因为我们是通过引用传递的,所以每个线程在内存中只需要一组sA和sB来执行函数调用

  • 如果改为按值传递,则在某个时间点,进程内存中可能有多达四个sA和sB副本(每个线程有两个集合),其中两个线程都在函数调用中交换处理器控制权

  • 在任何情况下,这里都不共享内存,因此该函数是线程安全的

抱歉,如果这个问题非常简单,线程已经炸了我的大脑:)


Pris

两个线程没有理由不持有对相同字符串的引用

此函数不是线程安全的,因为语句if(stringA==stringB)不是原子的。 首先从内存中提取
stringA
,然后才提取
stringb

让我们停留在
stringA==stringB==2


获取
stringA
,然后有一个上下文切换,stringA和stringB都变为3。然后获取
stringB
。您的函数将返回false(因为
2!=3
),尽管
stringA
始终等于
stringB

首先,不清楚为什么需要相同字符串的两个副本,如果它们总是具有相同的值


根据您描述的上下文,它可能是线程安全的,但简单地看一下它本身的函数,它不是线程安全的,因为在执行if条件时,字符串的值可能已经改变了。

您的问题对于
sA
sB
的声明位置有点模糊。听起来它们好像是在函数中声明的,在这种情况下,每个线程都有自己版本的
sA
sB
,这是正确的。但是,奇怪的是,它们在全局范围内被声明,事实并非如此。如果我对你的问题理解正确,你的意思是这两个是在局部范围内声明的,所以你的第一点是正确的。同样,你的第二点也是正确的


不过,你的第三点很棘手。在您的特定情况下,没有共享内存,因此您的程序是“线程安全”程序(不确定这是否是一种很好的方式)。但是,函数
AreStringsEqual
不是线程安全的。在将来的某个时候,您(或其他人)可以将该函数与共享的数据一起使用,而该函数本身不会防止这种使用。

如果sA和sB在线程之间共享,则该函数不是线程安全的

很可能在一个线程中执行函数AreStringsEqual时,另一个线程试图修改sA或sB或两者的值,然后会出现争用条件

当函数不修改值时,函数外部的代码可以修改

因此,最好使用“按值传递”,因为这样函数将在堆栈上具有本地副本
它保证是线程安全的

除非
QString
指定
operator==
是线程安全的,否则该函数不是线程安全的。
AreStringsEqual
的实现本身并不保护数据

通过这个实现,您将线程安全的责任交给了客户机。客户端必须确保参数和参数的内部数据在
AreStringsEqual
中时不会发生变化(例如被另一个线程)。因此,他们可能会发现自己制作了不必要的副本。这必须如何实现取决于
QString
的实现。甚至
std::string

对于并发上下文中的字符串,通常会在将字符串移动到并发上下文中之前进行复制。如果它真的需要被共享,你需要一些东西来保护它(比如锁)。对于基本集合(例如,
std::string
std::vector
),您希望避免在每次访问时锁定,因为这会降低性能,并且很容易失败。因此,如果必须共享非显式线程安全的对象,通常需要复制或锁定

因此,
AreStringsEqual
的实现不是线程安全的(同样,除非
bool QString::operator==(const QString&)const
保证是线程安全的)

但是,您对
的使用是相等的

QString sA = "hello";
QString sB = "world";
bool someFlag = AreStringsEqual(sA,sB);

这对于大多数字符串实现来说都很好,因为参数和它们的数据都是线程的本地数据。

什么是QString?它是否实现了“==”运算符?如果是这样,那么另一个线程可能会在==运算符的执行过程中更改stringA或stringB,这可能会使它不具有线程安全性。
sA
sB
someFlag
是全局的吗?即使它们是在本地范围内声明的,它们也是通过引用传递的,这意味着其他函数(和线程)也可以访问内存位置。@Ilykogan:我不确定我是否理解你的观点。如果你谈到我的第一段,那只是简单地说明他如何在整个程序中计算
sA
sB
的副本,这一点他是正确的。我的第二段讨论了线程安全问题,我认为这也是正确的。在任何情况下,
AreStringsEqual
使用pass-by-reference这一事实本身并不提供其他线程或函数