Linux 上 C 中的 POSIX 线程和全局变量

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9696923/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 05:10:07  来源:igfitidea点击:

POSIX threads and global variables in C on Linux

clinuxmultithreading

提问by randy newfield

If I have two threads and one global variable (one thread constantly loops to read the variable; the other constantly loops to write to it) would anything happen that shouldn't? (ex: exceptions, errors). If it, does what is a way to prevent this. I was reading about mutex locks and that they allow exclusive access to a variable to one thread. Does this mean that only that thread can read and write to it and no other?

如果我有两个线程和一个全局变量(一个线程不断循环读取变量;另一个线程不断循环写入变量)会发生什么不应该发生的事情吗?(例如:异常、错误)。如果是这样,有什么办法可以防止这种情况发生。我正在阅读有关互斥锁的信息,并且它们允许对一个线程的变量进行独占访问。这是否意味着只有该线程可以对其进行读写,而不能对其进行读写?

采纳答案by Jonathan Leffler

Would anything happen that shouldn't?

会发生不该发生的事情吗?

It depends in part on the type of the variables. If the variable is, say, a string (long array of characters), then if the writer and the reader access it at the same time, it is completely undefined what the reader will see.

这部分取决于变量的类型。如果变量是一个字符串(长字符数组),那么如果作者和读者同时访问它,那么读者将看到的内容是完全未定义的。

This is why mutexes and other coordinating mechanisms are provided by pthreads.

这就是 pthread 提供互斥锁和其他协调机制的原因。

Does this mean that only that thread can read and write to it and no other?

这是否意味着只有该线程可以对其进行读写,而不能对其进行读写?

Mutexes ensure that at most one thread that is using the mutex can have permission to proceed. All other threads using the same mutex will be held up until the first thread releases the mutex. Therefore, if the code is written properly, at any time, only one thread will be able to access the variable. If the code is not written properly, then:

互斥体确保最多一个使用互斥体的线程有权继续。使用相同互斥锁的所有其他线程将被暂停,直到第一个线程释放互斥锁。因此,如果代码编写得当,在任何时候,只有一个线程可以访问该变量。如果代码没有写好,那么:

  • one thread might access the variable without checking that it has permission to do so
  • one thread might acquire the mutex and never release it
  • one thread might destroy the mutex without notifying the other
  • 一个线程可能会访问该变量而不检查它是否有权这样做
  • 一个线程可能会获取互斥锁并且永远不会释放它
  • 一个线程可能会在不通知另一个线程的情况下销毁互斥锁

None of these is desirable behaviour, but the mere existence of a mutex does not prevent any of these happening.

这些都不是可取的行为,但互斥锁的存在并不能阻止任何这些发生。

Nevertheless, your code could reasonably use a mutex carefully and then the access to the global variable would be properly controlled. While it has permission via the mutex, either thread could modify the variable, or just read the variable. Either will be safe from interference by the other thread.

尽管如此,您的代码可以合理地谨慎使用互斥锁,然后对全局变量的访问将得到适当的控制。虽然它通过互斥锁获得许可,但任何一个线程都可以修改变量,或者只是读取变量。任何一个都不会受到另一个线程的干扰。

回答by Alok Save

Does this mean that only that thread can read and write to it and no other?

这是否意味着只有该线程可以对其进行读写,而不能对其进行读写?

It means that only one thread can read or write to the global variable at a time.
The two threads will not raceamongst themselves to access the global variable neither will they access it at the same time at any given point of time.

这意味着一次只有一个线程可以读取或写入全局变量。
这两个线程不会相互竞争以访问全局变量,也不会在任何给定时间点同时访问它。

In short the access to the global variable is Synchronized.

简而言之,对全局变量的访问是Synchronized

回答by tbert

If the threads truly are only one producer and only one consumer, then (barring compiler bugs) then

如果线程真的只有一个生产者和一个消费者,那么(除非编译器错误)然后

1) marking the variable as volatile, and

1) 将变量标记为 volatile,以及

2) making sure that it is correctly aligned, so as to avoid interleaved fetches and stores

2) 确保正确对齐,以避免交叉存取

will allow you to do this without locking.

将允许您在不锁定的情况下执行此操作。

回答by Soren

First; In C/C++ unsynchronized read/write of variable does not generate any exceptions or systemerror, BUT it can generate application level errors -- mostly because you are unlikely to fully understand how the memory is accessed, and whether it is atomic unless you look at the generated assembler. A multi core CPU may likely create hard-to-debug race conditions when you access shared memory without synchronization.

第一的; 在 C/C++ 中,变量的非同步读/写不会产生任何异常或系统错误,但它会产生应用程序级别的错误——主要是因为你不太可能完全理解内存是如何访问的,以及它是否是原子的,除非你看在生成的汇编程序中。当您在不同步的情况下访问共享内存时,多核 CPU 可能会产生难以调试的竞争条件。

Hence

因此

Second; You should always use synchronization -- such as mutex locks -- when dealing with shared memory. A mutex lock is cheap; so it will not really impact performance if done right. Rule of thumb; keep the lcok for as short as possible, such as just for the duration of reading/incrementing/writing the shared memory.

第二; 在处理共享内存时,您应该始终使用同步——例如互斥锁。互斥锁很便宜;所以如果做得好,它不会真正影响性能。经验法则;保持 lcok 尽可能短,例如仅在读取/增加/写入共享内存的持续时间内。

However, from your description, it sounds like that one of your threads is doing nothing BUT waiting for the shared meory to change state before doing something -- that is a bad multi-threaded design which cost unnecessary CPU burn, so

但是,根据您的描述,听起来您的一个线程除了等待共享内存更改状态再做某事之外什么都不做——这是一种糟糕的多线程设计,会消耗不必要的 CPU 消耗,所以

Third; Look at using semaphores (sem_create/wait/post) for synchronization between your threads if you are trying to send a "message" from one thread to the other

第三; 如果您尝试从一个线程向另一个线程发送“消息”,请查看使用信号量(sem_create/wait/post)在线程之间进行同步

回答by Jens Gustedt

As others already said, when communicating between threads through "normal" objects you have to take care of race conditions. Besides mutexes and other lock structures that are relatively heavy weight, the new C standard (C11) provides atomictypes and operations that are guaranteed to be race-free. Most modern processors provide instructions for such types and many modern compilers (in particular gccon linux) already provide their proper interfaces for such operations.

正如其他人已经说过的那样,当通过“正常”对象在线程之间进行通信时,您必须注意竞争条件。除了互斥锁和其他相对较重的锁结构之外,新的 C 标准 (C11) 还提供了保证无竞争的原子类型和操作。大多数现代处理器都为此类类型提供指令,许多现代编译器(特别是linux 上的gcc)已经为此类操作提供了适当的接口。