STL (std) thread safety issues

Discussion in 'C++' started by Philip V Pham, Jun 12, 2004.

  1. These questions apply to std vector, map, and cout:

    I am uncertain of the thread safety for reading/writing
    for std templates. I know if all threads are reading
    concurrently, it is thread safe. However, I have this situation:

    Case 1: map

    thread 1
    ---------
    someMapOb [key] = value //inserting new pair

    thread 2
    ---------

    interator pos;

    while (1==1)
    {
    for (pos = someMapOb.begin(); pos != someMapOb.end(), pos++ )
    {
    someValueOb = pos->second;

    someValueOb.foo ();

    }

    sleep (1)
    {


    Is safe for case 1 if I do that? I don't care
    if I miss a new inserted object in thread 2.
    If a new object inserted into the map, will the
    iterator be invalidated?
    The reason that I omit a mutex is to maximize performance.

    ---------------
    Case 2: queue

    thread 1
    --------
    someQueue.push ( value );

    thread 2
    ---------
    while ( ! someQueue.isEmpty ()
    {
    // display a status indicator
    // NOte, I don't pop or push the Q here
    }


    Is safe to call isEmpty() while the Q is being
    pushed?

    --------------------------

    Case 3: cout

    thread 1
    --------
    cout << "Thank you in advance for your help!" << endl;

    thread 2
    ---------
    cout << "Display....display ....." << endl;

    I know the screen output might be messed up,
    but would this concurrent cout cause a buffer overfloat
    crash?

    Thank you vey much for your help!
    I look forward to hear from your solutions.
    Philip V Pham, Jun 12, 2004
    #1
    1. Advertising

  2. Philip V Pham

    Pete C. Guest

    Philip V Pham wrote:
    > These questions apply to std vector, map, and cout:
    >
    > I am uncertain of the thread safety for reading/writing
    > for std templates. I know if all threads are reading
    > concurrently, it is thread safe. However, I have this situation:
    >

    <snip>

    Please don't multipost. If you must post in multiple groups, crosspost.
    Standard C++ does not support threading, so your question is off topic for
    this group. Please ask in a group for your implementation.

    - Pete
    Pete C., Jun 12, 2004
    #2
    1. Advertising

  3. STL has no built in thread support, so you'll have to extend the STL
    code with your own synchronization mechanisms to use STL in
    a multithreaded environment. Case1 and Case2 are clearly
    unsafe in my opinion. One of the troubles with thread programming
    is things can appear to work correctly in development, but strange
    bugs appear in the field when the execution environment can vary .
    You need to apply very strict logical reasoning
    in thread programming and be very conservative in your assumptions.
    After that, test your code on a multiprocessor machine.


    Case 1 - this is not thread safe, thread 1 may be preempted
    while performing the insertion, leaving the map in an undefined state,
    iteration over the map would be undefined. Inserting an element into
    a map rearranges the internal arrangement of elements, so if this is
    preempted
    the internal arrangement may not be in a valid state.

    You might want to look at the double-locking pattern which provides
    a more efficient mechanism to deal with locking shared data structures.
    Basically, a flag is set/reset to indicate a lock mutex lock is in place, if
    the flag is set, then thread gives up and try again later, otherwise the
    thread
    proceeds to acquire the lock and set the flag. This attempts to avoid the
    costly
    operation of trying to acquire the lock and failing.

    I'd have to look it up, but I think the map iterators would not be
    invalidated, that
    is an iterator would still "point" to the same element after an insertion,
    just
    that the internal links to its neighbours could be different, - again, if
    the rearrangment
    of the elements is preempted, imagine what chaos will result if you try to
    iterate
    over the elements...!


    case 2 - again, this is unlikely to work, the push operation is non-atomic
    so could be preempted mid-way, so you might have a situation where an
    element has been inserted intot the queue but the count of elements hasn't
    been updated...I in your example this is "harmless"situation, but I don't
    think I'd like
    to have it in my fly-by-wire navigation system


    case 3 - I don't know - cout could be implemented to serialize the two
    calls, but might not be for performance reasons with different
    implementations.

    dave

    "Philip V Pham" <> wrote in message
    news:EgGyc.1489$...
    > These questions apply to std vector, map, and cout:
    >
    > I am uncertain of the thread safety for reading/writing
    > for std templates. I know if all threads are reading
    > concurrently, it is thread safe. However, I have this situation:
    >
    > Case 1: map
    >
    > thread 1
    > ---------
    > someMapOb [key] = value //inserting new pair
    >
    > thread 2
    > ---------
    >
    > interator pos;
    >
    > while (1==1)
    > {
    > for (pos = someMapOb.begin(); pos != someMapOb.end(), pos++ )
    > {
    > someValueOb = pos->second;
    >
    > someValueOb.foo ();
    >
    > }
    >
    > sleep (1)
    > {
    >
    >
    > Is safe for case 1 if I do that? I don't care
    > if I miss a new inserted object in thread 2.
    > If a new object inserted into the map, will the
    > iterator be invalidated?
    > The reason that I omit a mutex is to maximize performance.
    >
    > ---------------
    > Case 2: queue
    >
    > thread 1
    > --------
    > someQueue.push ( value );
    >
    > thread 2
    > ---------
    > while ( ! someQueue.isEmpty ()
    > {
    > // display a status indicator
    > // NOte, I don't pop or push the Q here
    > }
    >
    >
    > Is safe to call isEmpty() while the Q is being
    > pushed?
    >
    > --------------------------
    >
    > Case 3: cout
    >
    > thread 1
    > --------
    > cout << "Thank you in advance for your help!" << endl;
    >
    > thread 2
    > ---------
    > cout << "Display....display ....." << endl;
    >
    > I know the screen output might be messed up,
    > but would this concurrent cout cause a buffer overfloat
    > crash?
    >
    > Thank you vey much for your help!
    > I look forward to hear from your solutions.
    >
    >
    >
    >
    Dave Townsend, Jun 12, 2004
    #3
  4. "Dave Townsend" <> wrote:
    > STL has no built in thread support, so you'll have to extend the STL
    > code with your own synchronization mechanisms to use STL in
    > a multithreaded environment.


    It is correct that the c++ standard does not require any multi-threading
    capabilities. However, implementations for multi-threaded environments
    typically have some support for multi-threading. In general, it is safe
    to read data structures from multiple threads but changing a data
    structure is allowed only for a thread with exclusive access to the data
    structure. Note that you typically have to inject some form of
    synchronization device after writing a data structure (eg. a mutex release)
    even if you can guarantee that the data structure is not accessed from
    multiple threads due to timing constraints: especially on multi processor
    systems the modified data is not always visible to other processors until
    it is explicitly written back.

    > Case1 and Case2 are clearly unsafe in my opinion.


    All three cases are unsafe.

    > You might want to look at the double-locking pattern which provides
    > a more efficient mechanism to deal with locking shared data structures.


    Note that the double-[checked] locking pattern does not work: it is a nice
    idea but actually introduces hard to find multi-threading bugs - after all,
    you explicitly handle multi-threading. I'm not a multi-threading expert
    (unless you count the advice "Avoid using multi-threadings! Use other
    approaches, e.g. multi-processing, where viable" as expertise...) to
    describe the reasons sufficiently well myself, I have only read arguments
    which make sense and reflect my experience with uses of the double-checked
    locking pattern. You might want to look at discussions e.g. in
    comp.lang.c++.moderated or google for a descriptions of the problems
    (<http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html>
    may be applicable to some extend).

    > I'd have to look it up, but I think the map iterators would not be
    > invalidated, that is an iterator would still "point" to the same element
    > after an insertion, just that the internal links to its neighbours could
    > be different, - again, if the rearrangment of the elements is preempted,
    > imagine what chaos will result if you try to iterate over the
    > elements...!


    On multi-processors choas results even if the rearrangement is not
    preempted: the changes are made to the processor's cache and it requires
    some form of multi-threading synchronization to make the changes appear
    for other processors. Typical processors for multi-processor machines often
    have special instructions to flush the cache and invalidate the
    corresponding cache sections of other caches. The user interface to these
    instructions differ between platforms but a mutex always does the trick.

    > case 3 - I don't know - cout could be implemented to serialize the two
    > calls, but might not be for performance reasons with different
    > implementations.


    It is very unlikely that this done: locking internal to a stream is simply
    the wrong abstraction level. You need to put locking around the stream. You
    might want to preformat the output into a thread-private string stream and
    then merely insert the resulting string at once into a thread protected
    'std::cout'. This has two positive effects: the output is not garbled and
    the time 'std::cout' is blocked is minimized.
    --
    <mailto:> <http://www.dietmar-kuehl.de/>
    <http://www.contendix.com> - Software Development & Consulting
    Dietmar Kuehl, Jun 14, 2004
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Peter Jansson
    Replies:
    5
    Views:
    6,263
    Ivan Vecerina
    Mar 17, 2005
  2. digz
    Replies:
    2
    Views:
    2,064
  3. grbgooglefan
    Replies:
    7
    Views:
    320
    James Kanze
    Dec 5, 2007
  4. Replies:
    6
    Views:
    1,027
    James Kanze
    Apr 5, 2008
  5. Scott Meyers
    Replies:
    2
    Views:
    922
    Scott Meyers
    Nov 6, 2010
Loading...

Share This Page