Threading question


#1

Morning chaps. (or whatever whereever you are)

when threading, what are the operations (if any) that are naturally atomic and therefore do not require synchronisation?

e.g can you get away with a simple getter…

int getNum() { return num_; }

where num_ can change at any time and this being called from another thread or will this one day go arse for tit and should be…

int getNum() { ScopedLock l ( critsec_ ); return num_; }

or how about…

[code]int& getNum()
{
return num_;
}

// or

int* getNum()
{
return &num_;
}[/code]

and what if num_ was declared volatile? I understand all volatile does is say “Here Jimmy! Divvent be putting num_ into any processor registers by way of optimisation now!”

In fact any threading advice, I want to hear it!


#2

so 20 odd folk here know nothing of threading?

decided to just use the synch primitives to be on the safe side.

I reckon unless something is a single asm instruction it needs locking.


#3

It needs locking even with a simple asm instruction.
Just think you have more than one CPU, and everything will become clearer.

Even if you read a value at time t, nothing prevent another cpu(thread) to write the same value. Worse, if you have 2 cpu, you’ll have cache coherency issue, making such call fails 100% of the time.

You need to protect anything shared, or use both atomic operation and memory barrier (like Interlocked functions under Win32, I don’t know of any under linux)

Have a look to erdani.org for good articles, and even this one:
http://erdani.org/publications/cuj-02-2001.html
to be on the safe side from compiler POV.


#4

I don’t think you need to protect operations that just read or write. You typically only need to protect operations that do read-modify-write.

Like:

if (flag) flag = false;

needs to be protected 'cos another thread could run between testing the value of “flag” and setting the value of flag. I just ran into this the other day in a device driver I was asked to clean up.

Or:

count++

needs to be either protected or use the atomic add; incrementing means that it’s reading the variable into a register, adding, and then writing it back. Another thread could write the variable during this process and so the wrong value would be written back to the variable.

But an unconditional get or set operation doesn’t typically need to be made atomic for the simple fact that a read or a write is intrinsically atomic, even on a multiple CPU machine.

Matt


#5

Adding volatle(sp?) as part of the variable declaration (like const and such) makes it always goto ram to read/write, never sending it to cache.


#6