Title: Can static arrays be safely accessed from multiple threads?
Tags: multithreading;delphi;delphi-xe2
Question: If each thread is guaranteed to only read/write to a specific subset of the array can multiple threads work on the same (static) array without resorting to critical sections, etc?

EDIT - This is for the specific case of arrays of non-reference-counted types and record/packed-records thereof.

If yes, any caveats?

My gut feeling is yes but my gut can sometimes be an unreliable source of information.

Comment: OK, I know what that means now. I'd call that fixed size but there you go. It makes no difference whether or not the size is fixed. It makes no difference whether or not the array is of global, local or class scope. It makes no difference whether or not the array is heap allocated or stack allocated. It's just a contiguous array of items.

Comment: No, my mistake. I'd never known that usage. I guess it must have been introduced after I learnt Delphi at the time that dynamic arrays were added, since all arrays before then were static. In any case, static or not makes no jamesgriffith@example.com.

Comment: @ArnaudBouchez That's a rather bizarre interpretation of "on the same (static) array". I take **the same** as meaning, well, the same single instance of an array. So, there's no copying here.

Comment: @ArnaudBouchez Yes copying may occur then. But the question makes it clear that copying does not occur.

Comment: @DavidHeffernan There is a difference, IMHO. Static arrays are allocated and copied when read (unless they are passed by reference, of course), whereas dynamic arrays are reference counted and have copy-on-write patterns, which may make a difference. It is (more or less) similar to the `shortstring / string` use patterns. In all cases, static arrays may not be thread-safe, in some situations: see my answer.

Comment: @DavidHeffernan Copying may occur when you pass the data to another sub function, e.g.

Comment: Fair enough.  As you say, in any case, there doesn't seem to be an obvious reason why concurrent access should be a problem but sometimes there are dark subtleties which confound such things.  Sometimes it is nice to be doubly certain.

Comment: @DavidHeffernan - yes, no copying.  All parties get a pointer to the array and an offset range to call their own.

Here is the accepted answer: Suppose that:


You have a single instance of an array (static or dynamic), and
The elements of the array are pure value types (i.e. contain no references), and
Each thread operates on disjoint sub-arrays, and
Nothing else in the system writes to the array whilst the threads are operating on it.


With these conditions, which I believe are met by your data structure and threading pattern, then all algorithms are thread-safe.

Comment for this answer: @J... Yes that is correct. So long as each thread operates on data private to that thread, then algorithms are thread-safe.
Comment for this answer: @arnold er, condition 4 certainly is necessary.
Comment for this answer: @leonardo that's right. And disjoint means that the slices do not overlap each other.
Comment for this answer: @DavidHeffernan - What do you mean for disjoint sub-arrays? Slices of the "main" array, distributed in some way to each thread so they don't access each other's slice?
Comment for this answer: @DavidHeffernan - thank you. I think that the OP needs to be aware that the process of distributing slices to each thread there may be some concurrency issues to be avoided, too.
Comment for this answer: @J... - I wasn't thinking in actually dividing the array. I understand that each thread will be assigned its own slice. I just wanted to point that if that assignment could occur in a thread (for example, worker threads assigning slices by themselves) then you still need to protect that part. But I understand that if this assignment is done on the main thread then it is not an issue. Gawd, just talking about threads is  convoluted.
Comment for this answer: I presume this would also be the case with reference type objects IF references to the same object are guaranteed to only exist within a single sub-array (ie: no common references shared between disjoint sub-arrays).
Comment for this answer: @LeonardoHerrera - the array in question will not be divided into new sub-arrays, if that's what you are thinking.  Application logic alone will define the ranges of array indices permissible for each thread to access.  Consider `arr1 = array[0..99] of double` and threads `0-9` where the n'th thread will work exclusively on array elements 10n->10n+9.
Comment for this answer: @DavidHeffeman, Is condition#4 really necessary? What is the difference of the main thread or another process writing to the array to the threads operating on it?

Here is another answer: No, this could not be thread safe, in some situations.

I see at least two reasons.

1. It will depend on the static array content.

If you use some non-reference counted types (like ```double, integer, bytes, shortstring```), there won't be any issue in most case (at least if data is read/only).

But if you use some reference-counted types (like ```string, interface```, or a nested dynamic array), you'll have to take care of thread safety.

That is:

```TMyType1: array[0..1] of integer; // thread-safe on reading
TMyType2: array[0..1] of string;  // may be confusing
```

Additional note: if your ```string``` is in fact shared among some sub-parts of the static array, you could have the reference count be confused. Unless you explicitly call ```UniqueString()``` for each one (inside a critical section, I suspect). For an array of ```double``` or ```integer```, you won't have this issue.

2. It will depend on the access concurrency 

Read access should be thread safe, even for reference counted type, but concurrent write may be confusing. For a ```string```, you may have GPF issues in some random cases, especially on a multi-core CPU.

Some safe implementation may be:


Use critical sections (smaller as possible, to reduce overhead) or other protection structures;
Use Copy-On-Write or a private per-thread copy of the content, to be sure;
Latest note (not about safety, but performance): Sharing an array among multiple CPUs may lead into performance penalties due to cache synchronization between CPUs. Performance is sometimes much better when you use separated arrays, ensuring their L1 caching window won't be shared among CPUs.


Be aware that such issues may be a nightmare to debug, on client side: multi-thread concurrency issues may occur randomly, and are very difficult to track. The safer, the better, unless you have explicit and proven performance issues.

Additional note: For your specific case of static array of double, with sub-part of the array accessed by one thread only, it is thread-safe. But there is no absolute rule of thread safeness in all situations, even for a static array. As soon as you use some reference-counted types, or some pointers, you may have random issues.

Comment for this answer: This answer is simply wrong in my view. The thrust of the question is that each thread operates on disjoint sub-arrays. And that only thread that owns each sub-array operates on it. That is thread-safe no matter what the element type is.
Comment for this answer: @J... If each thread operates on its own private sub-array then it makes no difference at all what's in the array. OK, the exception to that is if distinct sub-arrays contain references to a common object.
Comment for this answer: My point is that so long as the underlying data is not shared between threads then all algorithms are thread safe. Your answer would be better if it stated this up front because in fact that's exactly the situation that @J... is asking about.
Comment for this answer: @J... Yes... and no: they contain a pointer to some content, precessed by a reference count! The thread-safe issue is about reference count handling. Even if reference count access use an atomic low-level asm instruction, on multiple threads, you can have some race condition in case of concurrent update. For reading, it will be OK.
Comment for this answer: @DavidHeffernan As I added in my answer, you may have issues with disjoint sub-arrays, if e.g. some `string` are shared in those arrays - which may occur with `string`, unless you explicitly call `UniqueString()`.
Comment for this answer: @DavidHeffernan Reference-counted variables may be shared between threads, even if they are accessed via diverse sub arrays, since they are pointers to some shared content. That is, two threads may access to the same reference count from two diverse sides, at once. This is *indirect* shared data, but it may occur from another layer (e.g. UI). I've edited the answer to reflect this.
Comment for this answer: Good point - I should have been specific about the array type.  In this case the elements are packed records of doubles (which I think should be safe).
Comment for this answer: @DavidHeffernan - also a good point.  Arrays of reference counted objects hold pointers only, yes?

{'source': 'StackExchangeDataset', 'subset': 'stackoverflow.com', 'metadata': {'AnswerCount': 2, 'CommentCount': 8, 'ContentLicense': 'CC BY-SA 3.0', 'CreationDate': '2012:00:04/16/12', 'FavoriteCount': 3.0, 'PostTypeId': 1, 'Tags': '<multithreading><delphi><delphi-xe2>', 'Title': 'Can static arrays be safely accessed from multiple threads?', 'ViewCount': 3658, 'id': 10175037, 'user_AboutMe': '<p>I no longer participate here and will never return.  Stack Exchange is dead.</p>\n', 'user_AccountId': 128901.0, 'user_DisplayName': 'J...', 'user_Reputation': 30357.0, 'user_Views': 3985.0, 'user_id': 327083.0}}