For those static variables,
1. in global functions
2. in member functions in common object
3. as data member of common ojbect
4. as data member of self-defined TBB task object / filter oject / parallel_while oject
how are they shared among threads?
Could anybody please explain in detail if the answer differs between the 4 cases above.
However, it seems reasonable to assume that TBB has to synchronise a task object when spawned or executed, and a corrollary would be that a parent can read what a child has written without explicit synchronisation (if no other task could have intervened), but I have not seen an official statement to that effect (a request...) or clear indications in the code to allow me to easily verify this, and even then it seems more prudent for maintainability to use explicit synchronisation (right?), or otherwise at least a very clear indication in the program about what is going on.
For completeness (my own skippable take on old news, not specific to TBB):
Synchronisation by a mutex means that one thread writes something while holding a lock on a mutex, and then releases the mutex, which makes any changes visible in another thread after it acquires a lock on that mutex. A mutex is associated with a set of variables by programmer convention to disallow concurrent access, and although all other variables will also be synchronised (the association exists only in the programmer's head), the programmer should stick to that association to avoid problems (it's probably best to choose between using a lock the normal way on the one hand and lock-free synchronisation using atomics on the other hand, and to not make a confusing mix between the two styles). A mutex therefore has two functions: mutual exclusion (hence its name) that can block execution, and providing the illusion that all threads directly access main memory.
Atomics for their own sake can be freely read, written, incremented etc. without needing mutex protection.
Synchronisation by an atomic (other than use for its own sake) means that if one thread writes something, then assigns a message value to an atomic, another thread can read the written information after it has read the value from the atomic and recognised it as the appropriate message, but this style is often harder to get right than with the use of a mutex.