Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How low do you go before something gets thread-safe by itself?

I've been thinking, just how deep into everything do you have to go before something is automatically thread-safe?

Quick example:

int dat = 0;
void SetInt(int data)
{
    dat = data;
}

.. Would this method be considered threadsafe? I ussually wrap all my set-methods in mutex'es, just to be sure, but everytime I do so I can't help but to think that it's a useless perfomance overhead. I guess it all breaks down to the assembly the compiler generates? When are threads able to break into code? Per assembly-instruction or per code-line? Can a thread break in during the set-up or destruction of a method-stack? Would an instruction like i++ be considered threadsafe - and if not, what about ++i?

Lotsa questions here - and I dont expect a direct answer, but some info on the subject would be great :)

[UPDATE] Since it's clear for me now (thx to you guys <3 ), that the only atomic-guarenteed stuff in threading is an assembly instruction, I know came to think: What about mutex- and semaphore-wrapperclasses? Classes like this ussually use methods which makes callstacks - and custom semaphoreclasses that ussually utilizes some kind of internal counter can not be guarenteed to be atomic / threadsafe (whatever you wanna call it, as long as you know what I mean, I dont care :P )

like image 821
Meeh Avatar asked Dec 12 '08 07:12

Meeh


People also ask

What makes an object thread-safe?

A thread-safe object is one that always maintains a valid state, as observed by other classes and objects, even in a multithreaded environment.

When should I worry about thread-safety?

Save this answer. Show activity on this post. Thread safety becomes a concern if there is at least a single entry point which can be accessed by multiple threads. If a piece of code is accessed by multiple threads and is calling other method/class/etc., then all this code tree becomes vulnerable.

What is thread-safe rule?

An object is thread-safe for reading from multiple threads. For example, given an object A, it is safe to read A from thread 1 and from thread 2 simultaneously. If an object is being written to by one thread, then all reads and writes to that object on the same or other threads must be protected.

How do you know if something is thread-safe?

To test if the combination of two methods, a and b, is thread-safe, call them from two different threads. Put the complete test in a while loop iterating over all thread interleavings with the help from the class AllInterleavings from vmlens. Test if the result is either an after b or b after a.


1 Answers

considerations:

1) compiler optimization - does "dat" even exist as you planned? Unless it is an "externally observable" behavior, C/C++ abstract machine does not guarantee the compiler won't optimize it out. There might be no "dat" at all in your binary code, but instead you may be writing to a register, and threads will/may have different registers. Read C/C++ standard on the abstract machine or simply google for "volatile" and explore from there. C/C++ standard cares about single thread sanity, multiple threads can stumble over such optimization easily.

2) atomic stores. Anything that has a chance of crossing word boundaries will not be atomic. Int-s usually are, unless you pack them into a structure that has, for example, chars, and use directives to remove padding. But you need to analyze this aspect every time. Research your platform, google for "padding". Keep in mind that different CPUs have different rules.

3) multi-CPU issues. You wrote to "dat" on CPU0. Will the change be even seen on CPU1? Or will you just write to a local register? To cache? Are caches kept coherent you your platform? Is access guaranteed to be kept in order? Read on "weak memory model". Gogle for "memory_barriers.txt Linux" - it's a good start.

4) the use case. You intend to use "dat' after assignment - is that synchronized? But this is I guess obvious.

Usually "thread safety" does not go beyond guaranteeing that a function will work if called from different threads at the same time, but those calls must not be inter-dependent, i.e., they don't exchange any data with regard to that call. For example, you call malloc() from thread1 and thread2 and they both get memory, but they don't access each other's memory.

A counter-example would be strtok() which is not thread safe and would break even on unrelated calls.

As soon as your threads start to talk to each other over data, the usual thread safety doesn't guarantee much.

like image 93
n-alexander Avatar answered Sep 22 '22 09:09

n-alexander