Suppose I have a simple C string:

char *str = "I am a string". 

Question: Is it possible to access (read? Write?) From different streams to different characters of this line - will this cause any problems due to competitive access?

Question 2: is there a difference in the answer if the array is finite or dynamic?

Question 3: I assume that the answers to questions 1 and 2, whatever they may be, will be universal for C arrays of all kinds, not just strings. This is true?

PS In iOS, the GCD (Grand Central Dispatch) library, which is based on POSIX Threads, is used to work with threads, so I believe that the answer for pure C is also suitable for iOS.


Thank.

  • No, it is not, because does not imply any access synchronization tools, in fact, this is not an object in order to have any additional functionality (and thank God!). - mega
  • @mega, pay attention: I have three questions - I have specially singled out their type especially bold: 1-2-3. Can you somehow confirm what you wrote? For example, what you wrote follows that I need mutexes, if I walk along odd indices of this line in one stream, and even odd indices of others, and both streams will simply read what is recorded on these indices? - Stanislav Pankevich
  • @avp, @Free_ze, I answer here because of the limit: @avp, I understand, thanks for the comments. @Free_ze, thanks for the clarification, - I just did not immediately track how we went from access to the array to malloc. It is now clear. - Stanislav Pankevich
  • one
    @Stanislaw Pankevich, of course, you need to study and try these things. Just do not forget that the threads are evil. You can directly type it in Google and read. - avp
  • @Stanislaw Pankevich, I think my answer to your main question gives answers to additional ones, except for the third, perhaps, which I do not understand. In detail, of course @VladD and @Free_ze are right about the non-atomic nature of the variable. - mega

3 answers 3

  1. Read-only array is thread safe.
  2. If different threads are strictly written only to different elements, then thread safe.
  3. The variant of creating a string you cited is not entirely correct, since you are creating a pointer containing the address of a constant string. When accessing it for recording, the program may crash. Need to do so

     char str[] = "I am a string"; 
  • > 3. The variant of creating a string you cited is not entirely correct. Yes, you are right. When asking a question, I meant reading, and then at the end, before publishing, I added a 'record', as an option, and left the same form of the line entry. - Stanislav Pankevich
  • > If different threads are strictly written only to different elements, then thread-safe. Are you sure? It seems to me that the processor can update some piece of memory in its entirety (for example, a word) when writing one char. - dzhioev
  • > It seems to me that the processor can update some piece of memory in its entirety (for example, a word) when writing one char. Yes, it will update the cache line (usually 32/64 bytes). And, each time, before using the next cache line, the processor will be forced to request it entirely from memory [very long] or from the cache of a lower level [slightly faster] if the other processor changes it. Those. if the task was to increase the speed of processing the string in this way, alas, it would not work. - mega
  • 3
    @mega, I would add that the result will still be correct (i.e. if we change one byte, then the next bytes do not change ). - avp

The concept of thread safety in isolation from the pattern of use does not exist .

Consider not even an array, but a variable of type int . Is it thread safe? The correct answer depends on the semantics of use. If we store two packed char numbers in it, then there may well be a situation where we updated one but did not update the other, and the other stream will see the data in a non-consistent form. Or we store the element index in another, thread-safe array. Is the variable thread safe? No, because another stream can see the value of a variable that is larger than the maximum number of elements in the array.

The question of thread safety can be raised only after you have determined the semantics of your code.

Additional reading on the topic (there is about C #, but everything applies to Objective C).

  • @VladD, thanks for the clarification. The current semantics is as follows: there is an input string char * known length. Today, for the first time, I have thought about whether it is possible to organize enumeration along this line in two or more streams (only reading elements of this row from both streams) so that you can really win in speed compared to normal enumeration. Apple GCD API allows you to quickly organize any number of threads, and then I thought: firstly, if there are any problems with access to different bytes of this string, secondly, how to effectively split this string (in half? Even-odd?) - Stanislav Pankevich
  • @Stanislaw Pankevich: Look. If you access each item one by one, you only have a synchronization problem between two threads: the one that wrote the data to the cell of the array, and the one that reads it from there. That is, * if the reading thread starts after the write has occurred, you can read without restrictions * if the reading thread has started and the record has not yet occurred, you must ensure that the changes are visible in the reading flow. For this you need either mutex, or at least a memory barrier. - VladD
  • @VladD, I understand what you are describing. I have a simpler case: the line is already in finished form, then it is only expected to read this line from several threads. Based on all the answers / comments in this topic, it turns out that no problems with threads will arise, provided that I only read from any number of threads. Today, I will spend some time comparing different ways of organizing these flows for enumeration along the original line with the usual linear enumeration method. If you suddenly get surprised by the results - I will report them here. - Stanislav Pankevich
  • @Stanislaw Pankevich: cache locality may well affect the results of profiling. In addition, the cost of starting one stream can be much more than the cost of computing, so that the portions of the data are less than, say, 1K, I would not run the second stream. (Thread pool helps a lot, yes.) - VladD

Somewhere recently I read that the usual long-variable (64 bit) can be written in two sets of 32 bits each, i.e. atomicity of operations on simple types is not always guaranteed.

1) Regarding the array - if you do not change the pointer through which access will occur, then the elements of the array can be considered as independent. And there already depends on the type of elements.

2) There are no dynamic arrays in C, i.e. no difference. The "dynamism" of arrays is provided by special functions. It is worth considering their thread safety. For malloc:

Mutexes are used by these functions.

http://man7.org/linux/man-pages/man3/malloc.3.html

3) Strings in C are arrays of character elements with an additional element at the end. The same array as the rest.

  • Thanks for the answer. Regarding the second paragraph, I imagine this about myself, but I want to hear how they say it in the SO, more authoritative answer. - Stanislav Pankevich
  • one
    @Stanislaw Pankevich Anyway, this is a buffer of elements of some type that are accessible independently of each other. Synchronization is needed at the level of changing a single item and working with memory (as I understand it from mana, malloc is synchronized). - free_ze
  • one
    @Stanislaw Pankevich Judging by the text, the mutex is already used inside malloc, that is, if you have several threads trying to allocate memory at the same time (they just cause malloc at the same time), then the memory manager will not fail. Free fantasy: surely there is inside some kind of pointer to a free block in the heap and there is a risk to try to allocate memory twice in one place, without having time to mark it occupied. - free_ze
  • one
    @Stanislaw Pankevich, malloc() synchronized only in the sense that it is possible without thinking about the state of the internal structures of the allocator, to call malloc / calloc / realloc / free ... from several threads. But!!! You still can't do this from asynchronous signal handlers. - avp
  • one
    @Stanislaw Pankevich I talked about malloc in the context of differences between arrays on the stack and in the heap. I gave all the rest of the information in the answer: various elements can be changed independently, without the need for any synchronization. - free_ze