global variables and thread safety

This is a discussion on global variables and thread safety within the C Programming forums, part of the General Programming Boards category; I need a little clarification about thread-safety. I understand that some simple operations, like incrementing an index, might not be ...

  1. #1
    Registered User
    Join Date
    Aug 2005
    Posts
    13

    global variables and thread safety

    I need a little clarification about thread-safety. I understand that some simple operations, like incrementing an index, might not be atomic, but I'm wondering about the case below.

    I have a program with two threads. The second thread runs a loop. It's index is copied to a global variable, which the main thread uses to update the UI. Something like this:

    Code:
    for(i = 0; i < max; i ++) {
    ...
    gIndex = i;
    ...
    }
    The main thread only reads from gIndex, and never changes it. Is this thread-safe?

    Thanks!

  2. #2
    Registered User
    Join Date
    Jun 2005
    Posts
    6,174
    That depends on your definition of "thread-safe", but generally the answer would be "no". changing the value of a variable is not necessarily atomic.

    If your second thread was interrupted (or preempted) by the main thread while partway through the (non-atomic) process of executing the assignment "gIndex = i;", and the main thread read the value in gIndex, then the value received by the main thread would be indeterminate. There would be a non-zero probability of that occurring ..... and my definition of "thread-safe" in this example would probably include a zero probability of such an occurrence --- if both threads do their stuff many times, the probability tends to increase with execution time.

  3. #3
    and the hat of wrongness Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,422
    Assignment to primitive types such as int are almost always going to be atomic operations. The only place where this isn't likely is inside a packed struct, where the compiler has to manipulate two adjacent storage locations in order to write the int.

    > The main thread only reads from gIndex, and never changes it. Is this thread-safe?
    You need to make sure it's declared volatile, in order to make sure you keep checking it.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  4. #4
    Registered User
    Join Date
    Jun 2005
    Posts
    6,174
    Unfortunately, Salem, there are commonly used systems where assignment to int is not atomic. Windows operating systems are among them. There are special atomic operations in the win32 API (eg InterlockedExchange() for, effectively, atomically assigning the value of a 32 bit integer) to allow a programmer to cope with this.

    Declaring a variable volatile does not make access of it thread safe. With some systems, declaring a variable volatile disables some optimisation features. For example;
    Code:
       while (control_variable)
        {
            // code that does not change control_variable
        }
    can, in principle, be implemented with only one check of control_variable and making it volatile might cause it to be checked every time through the loop. However, the volatile keyword (like some others) is formally a hint to the compiler, and some compilers do choose to ignore that hint --- even if compiling for multithreaded usage.

  5. #5
    Registered User
    Join Date
    Aug 2005
    Posts
    13
    Quote Originally Posted by Salem

    > The main thread only reads from gIndex, and never changes it. Is this thread-safe?
    You need to make sure it's declared volatile, in order to make sure you keep checking it.
    I thought that global variables were checked each time in any case, as another subroutine might have accessed it. Is that wrong?

  6. #6
    and the hat of wrongness Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,422
    > InterlockedExchange
    That's far more than assignment - it assigns a new value and returns the old value.
    In other words
    Code:
    old = variable;
    variable = new;
    return old;
    Of course that kind of thing needs protecting from concurrent access problems.

    The stated problem was one thread write-only, and another thread read-only.

    Are you trying to tell me that
    var = value;
    can be interrupted?
    It's a single machine instruction, either it happens to completion or it hasn't happened at all.

    > I thought that global variables were checked each time in any case
    Global variables are the same as local variables, except for scope. The access rules do not change.
    Code:
    while ( var != 0 ) {
      // do stuff without ever touching var
    }
    If the compiler sees that the loop can never modify var, then it's perfectly reasonable to think that the compiler might only read the value once (or maybe never if it can figure out it's value), because there would be no need to.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  7. #7
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    Quote Originally Posted by MSDN
    MSDN: Interlocked Variable Access

    Simple reads and writes to properly-aligned 32-bit variables are atomic. In other words, when one thread is updating a 32-bit variable, you will not end up with only one portion of the variable updated; all 32 bits are updated in an atomic fashion. However, access is not guaranteed to be synchronized. If two threads are reading and writing from the same variable, you cannot determine if one thread will perform its read operation before the other performs its write operation.

    Simple reads and writes to properly aligned 64-bit variables are atomic on 64-bit Windows. Reads and writes to 64-bit values are not guaranteed to be atomic on 32-bit Windows. Reads and writes to variables of other sizes are not guaranteed to be atomic on any platform.
    ~~~~

  8. #8
    Registered User
    Join Date
    Aug 2005
    Posts
    13
    So, is the consensus then that I don't need mutexes here?

  9. #9
    and the hat of wrongness Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,422
    I don't think you "need" anything special in this specific case, but it's probably a good idea to get used to using the provided synchronisation functions so you do the right thing when it matters.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  10. #10
    Registered User
    Join Date
    Aug 2001
    Posts
    244
    simple operations can be made atomic by using the lock-prefix btw.
    (so write an inline function, that contains the operation (in assebly) with the lock prefix)
    signature under construction

  11. #11
    Registered User
    Join Date
    Aug 2005
    Posts
    13
    Quote Originally Posted by Salem
    I don't think you "need" anything special in this specific case, but it's probably a good idea to get used to using the provided synchronisation functions so you do the right thing when it matters.
    Okay. One more question then. As a rule of thumb, I assume you should protect reads as well as writes, since an unprotected read which is not atomic (like a 64-bit var) could be interrupted by a locked write of that same var. Correct?

    Thanks everyone for your advice!

  12. #12
    and the hat of wrongness Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,422
    Anything which is shared, and not atomic is open for trouble at some point (either reading or writing).

    Reading may get half the old value and half the new value.
    Writing may be merged with another write happening at the same time.

    Your original question was a very specific case.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. basic question about global variables
    By radeberger in forum C++ Programming
    Replies: 0
    Last Post: 04-06-2009, 12:54 AM
  2. Thread Prog in C language (seg fault)
    By kumars in forum C Programming
    Replies: 22
    Last Post: 10-09-2008, 01:17 PM
  3. Replies: 5
    Last Post: 08-06-2008, 09:59 AM
  4. esbo's data sharing example
    By esbo in forum C Programming
    Replies: 49
    Last Post: 01-08-2008, 10:07 PM
  5. Threads and global variables
    By Spark in forum C Programming
    Replies: 8
    Last Post: 05-29-2002, 02:08 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21