带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这一事实本身并不提供其他线程或函数