Multithreading. Do I need critical sections for read-only access?
Asked Answered
T

5

8

I have a bunch of threads. They should access a singleton containing configuration data which is initialized once when the singleton is created. Hence on the first access. So further actions on the singleton are just read-only. Do I need critical sections in this case?

Tocopherol answered 14/11, 2012 at 20:14 Comment(0)
B
7

It appears that because the data is created lazily on first access, the pointer or the reference to your singleton is read-write. This means that you do need a critical section.

In fact, the desire to avoid a critical section while keeping the lazy initialization in this situation has been so universally strong that it lead to the creation of the double-checked locking antipattern.

On the other hand, if you were to initialize your singleton eagerly before the reads, you would be able to avoid a critical section for accessing an immutable object through a constant pointer / reference.

Battledore answered 14/11, 2012 at 20:18 Comment(1)
Your link says that in C++11 locking is not needed in the lazily initialised singleton.Janycejanyte
B
1

No. If you're simply reading this data after it is fully initialized and the data never changes then there is no possibility of a race condition occurring.

However, if the data is written to/modified in any way then you will need to synchronize access to it, i.e., lock the data before writing.

Bailes answered 14/11, 2012 at 20:16 Comment(1)
@DevNoob: Yes, I was just about to edit my response because I saw this: Hence on the first access. So you'll need to protect it while it is being initialized. However, if this data is always used by your program (i.e., there is no way (or a very small chance) that your program will run and this data will not be initialized) you don't really need lazy initialization, it's not saving you anything. Either way, the data needs to be protected while it is being written. After that you can read and read away.Bailes
P
1

If you only ever read some shared data, and never write, you do not need to synchronize access.

You only need to synchronize when a shared piece of data is both read and written at potentially the same time.

Pareira answered 14/11, 2012 at 20:17 Comment(0)
S
1

I understand your question as there is lazy initialization in your singleton. It is initialized only for the first read.

The next consecutive reads are thread safe. But what about concurrent read during initialization?

If you have situation like this:

SomeConfig& SomeConfig::getInstance()
{
   static SomeConfig instance;
   return instance;
} 

Then it depends on your compiler. According to this post in C++03 it was implementation dependent if this static initialization is thread safe.

For C++11 it is thread safe - see answers to this post, citation:

such a variable is initialized the first time control passes through its declaration; such a variable is considered initialized upon the completion of its initialization. [...] If control enters the declaration concurrently while the variable is being initialized, the concurrent execution shall wait for completion of the initialization.

It is worth to note that read only access to global variables is thread safe.

Septuagesima answered 14/11, 2012 at 20:25 Comment(0)
A
0

The official rule in the spec is that a data race is when one thread can write to a variable concurrently while another thread read or writes the same variable.

If you can prove that the initialization has to take place before any of the readers can read, then you do not need synchronization. This is most often accomplished by initializing before creating (or synchronizing) the threads, or by using static storage variables, which C++11 guarantees some synchronization on

Align answered 3/9, 2013 at 15:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.