-3

Consider following posix thread code:

void *thr(void *arg)
{
    static int i = 0;

    return ++i;
}

I think that this is atomic and safe operation as it should translate in on assembly instruction inc i for change of value. However, I am not a great expert of internals of cpu and multithreading thus I am doubtful.

EDIT: Since it is not safe say I use mutex lock to make this safe then how much extra cost would it be in terms of time. EDIT: I got my answer from Overhead of pthread mutexes for time cost. Thanks a bunch.

Community
  • 1
  • 1
Shiv
  • 1,912
  • 1
  • 15
  • 21
  • 2
    In general, if your basis for thinking something is thread-safe is that you have an idea of what assembly code the compiler is likely to generate, then -- you don't really have a basis for thinking it's thread-safe. Because realistically, if your compiler does any sort of optimization at all, you can never really rely on your assumptions. Compilers do some shockingly clever things to squeeze one or two cycles. (But regardless, in your case I'm not sure what you think `inc i` is. Your system's primitive for incrementing a *register* might be atomic -- but probably not a *memory location*!) – ruakh Nov 22 '15 at 02:27
  • http://stackoverflow.com/questions/680097/ive-heard-i-isnt-thread-safe-is-i-thread-safe – 001 Nov 22 '15 at 02:27
  • @ruakh Typical x86 CPUs have an instruction for incrementing a memory location, but it's not atomic unless specifically requested. And no sane compiler would be likely to request an atomic operation in this case because it's much more expensive and the compiler has no reason to think it needs it. – David Schwartz Nov 22 '15 at 02:29
  • Thanks for your answers. @DavidSchwartz how can I request for atomic operation to compiler to directly increment the value in memory? – Shiv Nov 22 '15 at 02:35
  • It depends. There's no standard C/pthreads way to do it. Your compiler may offer intrinsics, you can use inline assembly, or you can use a library that provides them. Or just use a lock. – David Schwartz Nov 22 '15 at 02:37

2 Answers2

5

It's neither atomic nor safe for many reasons:

  1. No standard says it is. So if happens to be, it's only by luck and you'd be crazy to rely on that.

  2. Who says a single instruction is atomic? An increment requires a fetch, an add, and a store. On most CPUs, that's not atomic. (Why do you think x86 CPUs offer a LOCK prefix? If single instructions were already atomic, what purpose would it serve?)

  3. The compiler can optimize in all kinds of crazy ways.

But more importantly, you are making a very fundamental mistake. It is impossible to conclude that something is safe merely because you can't think of any way it can fail. This will never work and you should never, ever do it. If you don't have guarantees, and you don't in this case, it's not safe.

Since it is not safe say I use mutex lock to make this safe then how much extra cost would it be in terms of time.

Probably very little. On most platforms, acquiring an uncontested lock is roughly comparable in cost to an atomic increment. Since you need an atomic increment anyway, you have to pay this cost somehow.

In other words, in the uncontested case (where two threads don't try to increment at the same time), a lock/increment/unlock will perform about the same as an atomic increment on most platforms. However, if there's a lot of contention, the atomic increment will perform much better.

If you don't have to deal with contention super-effectively, just use a lock and be done with it. If you do, then you should be using some platform or library that provides effective ways to deal with contention, such as a C++ implementation with std::atomic, a library that provides inline assembly atomic operations, or a compiler with atomic intrinsics.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
4

The operation is not atomic. It implies reading the variable from memory (it's a variable with static storage), incrementing it and then storing back in memory.

nnn
  • 3,980
  • 1
  • 13
  • 17