C++ 混合C和C的线程同步++;

C++ 混合C和C的线程同步++;,c++,c,multithreading,thread-synchronization,C++,C,Multithreading,Thread Synchronization,我有一个多线程程序,主线程是第三方(无法更改)和纯C。我的任务是围绕它构建新的模块(在C++中),这些模块部分驻留在其他线程中,需要使用C程序的接口。基本上只是读取一些在C线程中存储和更新的变量(int、float,不复杂) 现在我的问题是:我如何确保在访问这些变量时不会从C接口中得到垃圾,因为我不能在读取时使用互斥锁来锁定它。这可能吗?还是说写浮点/int是一种原子操作?你不能。读写任何东西都不是一个原子操作,如果你不能更改C代码,那你就倒霉了。同步始终需要同步两个部分 你最好的办法是让第三方

我有一个多线程程序,主线程是第三方(无法更改)和纯C。我的任务是围绕它构建新的模块(在C++中),这些模块部分驻留在其他线程中,需要使用C程序的接口。基本上只是读取一些在C线程中存储和更新的变量(int、float,不复杂)


现在我的问题是:我如何确保在访问这些变量时不会从C接口中得到垃圾,因为我不能在读取时使用互斥锁来锁定它。这可能吗?还是说写浮点/int是一种原子操作?

你不能。读写任何东西都不是一个原子操作,如果你不能更改C代码,那你就倒霉了。同步始终需要同步两个部分


你最好的办法是让第三方确保他们的部件线程安全和/或与你共享一个锁定机制。

你不能。在这种情况下,唯一正确的方法是只使用调用C线程提供给函数的参数,而不存储对它们的任何引用。在一般情况下,无法保证任何变量都不会被修改


您需要重新考虑您的体系结构,这样才不会出现这种需要。

如果您无法确保设置变量值的代码是同步的,那么在读取时加锁是毫无意义的,也不会起作用。这不仅是操作的原子性,也是数据的可见性——对这些变量的更新可能对其他线程不可见

如果控制主线程,则必须为每个必须访问的线程创建一个新变量,从主线程访问该变量,并使用锁设置新创建变量的值。然后,从其他线程只访问那些同步的变量

int myVal = 0;

int main() {
  while(!shouldQuit()) {
    doSomeIndependentStuff();
    pthread_lock(&mutex);
    myVal = independentGlobalVal;
    pthread_unlock(&mutex);
  }
}

int getMyVal() {
  int retVal = 0;
  pthread_lock(&mutex);
  retVal  = myVal;
  pthread_unlock(&mutex);
  return retval;
}

语句,如“写浮点/ int [IS ]是一个原子操作”,不幸的是,在C++或C++中没有很好的定义(尽管使用C++中的<代码> STD::原子< /代码>,C11的StDATOM .H方法可以帮助这里——但是这不会帮助你用C互操作来修改你不能修改的库,所以你可以忽略它。

您可以在特定的编译器和平台上找到关于这些问题的指导—例如,您可能会发现,在大多数平台上,对齐的32位或64位读写将是原子的,如果对齐的话,并且大多数编译器将适当地对齐它们

然而,沿着这条路走下去的是疯狂。如果涉及多个线程,只需使用POSIX/P螺纹功能,比如C和C++都容易访问的功能,以防止对线程间共享的状态的任何访问。

因为你不能修改C代码,你可能必须在C++代码中做所有的锁定,然后才调用C库,然后解锁。如果您可以阅读但不能修改C代码,或者文档非常清楚线程/共享模型,那么您可能可以使用细粒度锁定策略,但在没有任何表示瓶颈的分析的情况下,首先,我将使用一个全局锁来保护对C API的每一次访问。

混合使用C/C++与这个问题没有多大关系。我建议将这个线程称为“与外部库的数据同步”或类似的东西。什么是CPU和操作系统?我认为这将对什么是原子的和什么不是原子的产生影响。此外,缓存总是会有问题,即其他线程已更改了值,但尚未将其写入主RAM,因此最好不要在值稍微过时是致命问题的情况下执行任何操作。这就是我所想的。。。我不想让它依赖于一些特殊的体系结构。@ FEWU——你能给出关于这个问题的“主线程”和C部分的结构的更多细节,以及C++程序如何与它交互?你提到主线程是C,你不能改变它,但是这提出了一个问题:C++线程是如何首先被开除的?另外(这应该是第一个问题)——C代码本身是如何记录wrt线程安全的?当然,答案可能是“没什么”,但至少是值得一试的。主线程是C(实际上是由Matlab Simulink生成的代码),它是我在C++中实现的一个定义接口,因为我必须与另一个C++库(也是第三方)接口。在这个C++实现中,我开开C++线程。关于你的第二个问题:正如你所怀疑的那样,线程安全并没有任何问题。你通常可以在你自己的调用代码中进行所有的锁定——保护对未知代码的每次调用,这样在C库中一次只能有一个线程。由于这有效地实现了对C库的单线程访问,因此它几乎可以保证正常工作。自从有了简陋的本机库之后,这种技术就被用来与简陋的本机库进行交互。我想这就是我要做的。要求第三方创建一个接口,如“代码”> WordNoWaldValx(int NeVALVE)<代码>,每次它们更新值时,我可以将变量复制到我的C++世界,在那里我可以锁定/解锁访问。如果写不同步,锁定读只是点。C11也有原子。stdatomic.hI从未建议锁定只读。我建议锁定对C库的任何调用,这将包含所有读写操作(通过本机库)。如果有任何实际共享状态(例如,共享库所公开的全局变量),当您访问C++时,需要对C++进行锁定。@ DARIZZ——在仔细阅读OP的问题描述之后,您似乎有一点——他暗示“主线程”是C代码的,并且将完全留在C代码中。这会使事情复杂化。这似乎不太可能是设计——C++线程是如何获得的