成员函数线程安全吗?
Posted
技术标签:
【中文标题】成员函数线程安全吗?【英文标题】:Is A Member Function Thread Safe? 【发布时间】:2015-07-15 00:00:04 【问题描述】:我在一个服务器对象中有多个执行相同任务的线程。这些线程使用 Server::* 例程初始化。
在这个例程中,有一个带有一些处理的无限循环。
我想知道对多个线程使用相同的方法是否是线程安全的?难怪类的字段,如果我想读或写它,我会使用互斥锁。但是例程本身呢?
既然函数是一个地址,那么那些线程将运行在同一个内存区域?
我需要为每个线程创建一个具有相同代码的方法吗?
Ps:我使用 std::mutex(&Server::Task, this)
【问题讨论】:
只要您的互斥锁可以防止所有形式的潜在损坏数据,您应该没问题。 是的,但这是我的问题:在成员函数的情况下,不是每条指令都可能损坏数据吗?我的“while”指令会被同时执行的多个线程破坏吗?由于此方法具有唯一的地址... 很不清楚你在问什么。请提供一个具体的、完整的小例子。 你似乎混淆了 code 和 data。 【参考方案1】:两个线程同时运行同一个函数没有问题(不管是不是成员函数)。
就指令而言,这类似于如果您有两个线程同时读取同一个字段 - 没关系,它们都获得相同的值。 (当你一写一读,或者两写,你就可以开始有竞争条件了)
【讨论】:
谢谢。我知道经典的 C 函数,但我对成员函数有强烈的怀疑,因为它们属于对象的实例。因此,我倾向于将成员函数视为需要互斥的字段或数据。 @ThibaudAuzou:你明白为什么共享数据需要被互斥体保护吗?【参考方案2】:在 C++ 中,每个线程都分配有自己的调用堆栈。这意味着仅存在于给定线程的调用堆栈范围内的所有局部变量都只属于该线程。但是,在共享数据或资源的情况下,例如全局数据结构或数据库,不同的线程可能同时访问这些。解决此同步问题的一种方法是使用 std::mutex
,您已经在这样做了。
【讨论】:
【参考方案3】:虽然函数本身可能是内存中相同的地址,就其在表中的位置而言,您不会从多个位置写入它,但函数本身是不可变的,并且该函数内部的局部变量将按线程堆叠.
如果您的写入受到保护并且提取不会提取过时的数据,那么您在大多数架构和实现中可能需要的安全。
【讨论】:
【参考方案4】:在幕后,int Server::Task(std::string arg)
与int Server__Task(Server* this, std::string arg)
非常相似。就像多个线程可以执行相同的函数一样,多个线程也可以执行相同的成员函数——即使使用相同的参数。
互斥锁确保不会发生冲突的更改,并且每个线程都能看到之前的每个更改。但是由于代码没有机会,因此您不需要互斥体,就像字符串文字不需要互斥体一样。
【讨论】:
以上是关于成员函数线程安全吗?的主要内容,如果未能解决你的问题,请参考以下文章