简体   繁体   English

带线程的 C/C++ 数组 - 我需要使用互斥锁还是锁?

[英]C/C++ arrays with threads - do I need to use mutexes or locks?

I am new to using threads and have read a lot about how data is shared and protected.我是使用线程的新手,并且已经阅读了很多关于如何共享和保护数据的内容。 But I have also not really got a good grasp of using mutexes and locks to protect data.但我也没有真正掌握使用互斥锁和锁来保护数据。

Below is a description of the problem I will be working on.下面是我将要解决的问题的描述。 The important thing to note is that it will be time-critical, so I need to reduce overheads as much as possible.需要注意的重要一点是,这将是时间紧迫的,所以我需要尽可能地减少开销。

I have two fixed-size double arrays.我有两个固定大小的双数组。

  • The first array will provide data for subsequent calculations.第一个数组将为后续计算提供数据。 Threads will read values from it, but it will never be modified.线程将从它读取值,但它永远不会被修改。 An element may be read at some time by any of the threads.某个元素可能会在某个时间被任何线程读取。

  • The second array will be used to store the results of the calculations performed by the threads.第二个数组将用于存储线程执行的计算结果。 An element of this array will only ever be updated by one thread, and probably only once when the result value这个数组的一个元素只会被一个线程更新,并且可能只有一次当结果值
    is written to it.是写给它的。

My questions then:我的问题是:

  1. Do I really need to use a mutex in a thread each time I access the data from the read-only array?每次访问只读数组中的数据时,我真的需要在线程中使用互斥锁吗? If so, could you explain why?如果是这样,你能解释一下原因吗?

  2. Do I need to use a mutex in a thread when it writes to the result array even though this will be the only thread that ever writes to this element?当线程写入结果数组时,我是否需要在线程中使用互斥锁,即使这将是唯一写入该元素的线程?

  3. Should I use atomic data types, and will there be any significant time overhead if I do?我应该使用原子数据类型吗,如果我这样做会不会有任何显着的时间开销?

  4. Many answers to this type of question seem to be - no, you don't need the mutex if your variables are aligned.此类问题的许多答案似乎是 - 不,如果您的变量对齐,则不需要互斥锁。 Would my array elements in this example be aligned, or is there some way to ensure they are?我在这个例子中的数组元素会对齐,还是有什么方法可以确保它们对齐?

The code will be implemented on 64bit Linux.该代码将在 64 位 Linux 上实现。 I am planning on using Boost libraries for multithreading.我计划使用 Boost 库进行多线程处理。

I have been mulling this over and looking all over the web for days, and once posted, the answer and clear explanations came back in literally seconds.几天来我一直在仔细考虑这个问题,并在整个网络上查看,一旦发布,答案和清晰的解释在几秒钟内就回来了。 There is an "accepted answer," but all the answers and comments were equally helpful.有一个“接受的答案”,但所有的答案和评论都同样有帮助。

  1. Do I really need to use a mutex in a thread each time I access the data from the read-only array?每次访问只读数组中的数据时,我真的需要在线程中使用互斥锁吗? If so could you explain why?如果是,你能解释一下原因吗?

No. Because the data is never modified, there cannot be synchronization problem.不会。因为数据永远不会被修改,所以不会有同步问题。

  1. Do I need to use a mutex in a thread when it writes to the result array even though this will be the only thread that ever writes to this element?当线程写入结果数组时,我是否需要在线程中使用互斥锁,即使这将是唯一写入该元素的线程?

Depends.要看。

  1. If any other thread is going to read the element, you need synchronization.如果任何其他线程要读取该元素,则需要同步。
  2. If any thread may modify the size of the vector, you need synchronization.如果任何线程可能会修改向量的大小,则需要同步。

In any case, take care of not writing into adjacent memory locations by different threads a lot.在任何情况下,请注意不要由不同的线程大量写入相邻的内存位置。 That could destroy the performance.这可能会破坏性能。 See "false sharing".参见“虚假共享”。 Considering, you probably don't have a lot of cores and therefore not a lot of threads and you say write is done only once, this is probably not going to be a significant problem though.考虑到,您可能没有很多内核,因此没有很多线程,并且您说写入仅完成一次,但这可能不会成为一个重大问题。

  1. Should I use atomic data types and will there be any significant time over head if I do?我应该使用原子数据类型吗,如果我这样做会不会有任何重要的时间开销?

If you use locks (mutex), atomic variables are not necessary (and they do have overhead).如果您使用锁(互斥),则不需要原子变量(并且它们确实有开销)。 If you need no synchronization, atomic variables are not necessary.如果不需要同步,则不需要原子变量。 If you need synchronization, then atomic variables can be used to avoid locks in some cases.如果您需要同步,那么在某些情况下可以使用原子变量来避免锁定。 In which cases can you use atomics instead of locks... is more complicated and beyond the scope of this question I think.在哪些情况下你可以使用原子而不是锁......我认为这更复杂,超出了这个问题的范围。

Given the description of your situation in the comments, it seems that no synchronization is required at all and therefore no atomics nor locks.鉴于您在评论中的情况描述,似乎根本不需要同步,因此不需要原子或锁。

  1. ...Would my array elements in this example be aligned, or is there some way to ensure they are? ...在这个例子中我的数组元素是否会对齐,或者有什么方法可以确保它们对齐?

As pointed out by Arvid, you can request specific alignment using the alginas keyword which was introduced in c++11.正如 Arvid 所指出的,您可以使用 c++11 中引入的alginas关键字请求特定对齐。 Pre c++11, you may resort to compiler specific extensions: https://gcc.gnu.org/onlinedocs/gcc-5.1.0/gcc/Variable-Attributes.html在 c++11 之前,您可以求助于编译器特定的扩展: https : //gcc.gnu.org/onlinedocs/gcc-5.1.0/gcc/Variable-Attributes.html

Under the two conditions given, there's no need for mutexes.在给定的两个条件下,不需要互斥锁。 Remember every use of a mutex (or any synchronization construct) is a performance overhead.请记住,每次使用互斥锁(或任何同步构造)都是一种性能开销。 So you want to avoid them as much as possible (without compromising correct code, of course).所以你想尽可能地避免它们(当然不影响正确的代码)。

  1. No. Mutexes are not needed since threads are only reading the array.不。不需要互斥体,因为线程只读取数组。

  2. No. Since each thread only writes to a distinct memory location, no race condition is possible.不可以。由于每个线程只写入不同的内存位置,因此不可能出现竞争条件。

  3. No. There's no need for atomic access to objects here.不。这里不需要对对象进行原子访问。 In fact, using atomic objects could affect the performance negatively as it prevents the optimization possibilities such as re-ordering operations.事实上,使用原子对象可能会对性能产生负面影响,因为它会阻止优化的可能性,例如重新排序操作。

The only time you need to use Locks is when data is modified on a shared resource.只有在共享资源上的数据被修改时才需要使用锁。 Eg if some threads where used to write data and some used to read data (in both cases from the same resource) then you only need a lock for when writing is done.例如,如果一些线程用于写入数据而一些用于读取数据(在这两种情况下都来自同一资源),那么您只需要在写入完成时锁定。 This is to prevent whats known as "race".这是为了防止所谓的“种族”。

There is good information of race on google for when you make programs that manipulate data on a shared resource.当您制作在共享资源上操作数据的程序时,谷歌上有很好的种族信息。

You are on the right track.你走在正确的轨道上。

1) For the first array (read only) , you do not need to utilize a mutex lock for it. 1)对于第一个数组(只读),您不需要为其使用互斥锁。 Since the threads are just reading not altering the data there is no way a thread can corrupt the data for another thread由于线程只是读取而不是更改数据,因此线程无法破坏另一个线程的数据

2) I'm a little confused by this question. 2)我对这个问题有点困惑。 If you know that thread 1 will only write an element to array slot 1 and thread 2 will only write to array slot 2 then you do not need a mutex lock.如果您知道线程 1 只会将元素写入数组插槽 1,而线程 2 只会写入数组插槽 2,那么您不需要互斥锁。 However I'm not sure how your achieving this property.但是我不确定你是如何实现这个属性的。 If my above statement is not correct for your situation you would definitely need a mutex lock.如果我的上述陈述不适合您的情况,您肯定需要一个互斥锁。

3) Given the definition of atomic: 3) 鉴于原子的定义:

Atomic types are types that encapsulate a value whose access is guaranteed to not cause data races and can be used to synchronize memory accesses among different threads.原子类型是封装一个值的类型,该值的访问保证不会引起数据竞争,并且可用于同步不同线程之间的内存访问。

Key note, a mutex lock is atomic meaning that there is only 1 assembly instruction needed to grab/release a lock.重点说明,互斥锁是原子的,这意味着只需要 1 条汇编指令即可获取/释放锁。 If it required 2 assembly instructions to grab/release a lock, a lock would not be thread safe.如果需要 2 个组装指令来抓取/释放锁,那么锁就不是线程安全的。 For example, if thread 1 attempted to grab a lock and was switched to thread 2, thread 2 would grab the lock.例如,如果线程 1 尝试获取锁并被切换到线程 2,线程 2 将获取锁。

Use of atomic data types would decrease your overhead but not significantly.使用原子数据类型会减少你的开销,但不会显着。

4) I'm not sure how you can assure your variables are lined. 4)我不确定你如何确保你的变量是内衬的。 Since threads can switch at any moment in your program (Your OS determines when a thread switches)由于线程可以在您的程序中随时切换(您的操作系统确定线程何时切换)

Hope this helps希望这可以帮助

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM