Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8006963
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 4, 20262026-06-04T17:40:46+00:00 2026-06-04T17:40:46+00:00

I want access a STL based container read-only from parallel running threads. Without using

  • 0

I want access a STL based container read-only from parallel running threads. Without using any user implemented locking. The base of the following code is C++11 with a proper implementation of the standard.

http://gcc.gnu.org/onlinedocs/libstdc++/manual/using_concurrency.html
http://www.sgi.com/tech/stl/thread_safety.html
http://www.hpl.hp.com/personal/Hans_Boehm/c++mm/threadsintro.html
http://www.open-std.org/jtc1/sc22/wg21/ (current draft or N3337, which is essentially C++11 with minor errors and typos corrected)

23.2.2 Container data races [container.requirements.dataraces]

For purposes of avoiding data races (17.6.5.9), implementations shall
consider the following functions to be const: begin, end, rbegin,
rend, front, back, data, find, lower_bound, upper_bound, equal_range,
at and, except in associative or unordered associative containers,
operator[].

Notwithstanding (17.6.5.9), implementations are required
to avoid data races when the contents of the con- tained object in
different elements in the same sequence, excepting vector<bool>, are
modified concurrently.

[ Note: For a vector<int> x with a size greater
than one, x[1] = 5 and *x.begin() = 10 can be executed concurrently
without a data race, but x[0] = 5 and *x.begin() = 10 executed
concurrently may result in a data race. As an exception to the general
rule, for a vector<bool> y, y[0] = true may race with y[1]
= true. — end note ]

and

17.6.5.9 Data race avoidance [res.on.data.races] 1 This section specifies requirements that implementations shall meet to prevent data
races (1.10). Every standard library function shall meet each
requirement unless otherwise specified. Implementations may prevent
data races in cases other than those specified below.

2 A C++ standard
library function shall not directly or indirectly access objects
(1.10) accessible by threads other than the current thread unless
the objects are accessed directly or indirectly via the function’s
argu- ments, including this.

3 A C++ standard library function shall
not directly or indirectly modify objects (1.10) accessible by threads
other than the current thread unless the objects are accessed directly
or indirectly via the function’s non-const arguments, including
this.

4 [ Note: This means, for example, that implementations can’t
use a static object for internal purposes without synchronization
because it could cause a data race even in programs that do not
explicitly share objects between threads. — end note ]

5 A C++ standard library function shall not access objects indirectly
accessible via its arguments or via elements of its container
arguments except by invoking functions required by its specification
on those container elements.

6 Operations on iterators obtained by
calling a standard library container or string member function may
access the underlying container, but shall not modify it. [ Note: In
particular, container operations that invalidate iterators conflict
with operations on iterators associated with that container. — end
note ]

7 Implementations may share their own internal objects between
threads if the objects are not visible to users and are protected
against data races.

8 Unless otherwise specified, C++ standard library
functions shall perform all operations solely within the current
thread if those operations have effects that are visible (1.10) to
users.

9 [ Note: This allows implementations to parallelize operations
if there are no visible side effects. — end note ]

Conclusion
Containers are not thread safe! But it is safe to call const functions on containers from multiple parallel threads. So it is possible to do read-only operations from parallel threads without locking.
Am I right?

I pretend that their doesn’t exist any faulty implementation and every implementation of the C++11 standard is correct.

Sample:

// concurrent thread access to a stl container
// g++ -std=gnu++11 -o p_read p_read.cpp -pthread -Wall -pedantic && ./p_read
#include <iostream>
#include <iomanip>
#include <string>
#include <unistd.h>

#include <thread>
#include <mutex>

#include <map>

#include <cstdlib>
#include <ctime>
using namespace std;

// new in C++11
using str_map = map<string, string>;

// thread is new in C++11
// to_string() is new in C++11

mutex m;
const unsigned int MAP_SIZE = 10000;

void fill_map(str_map& store) {
    int key_nr;
    string mapped_value;
    string key;

    while (store.size() < MAP_SIZE) {
        // 0 - 9999
        key_nr = rand() % MAP_SIZE;

        // convert number to string
        mapped_value = to_string(key_nr);
        key = "key_" + mapped_value;

        pair<string, string> value(key, mapped_value);
        store.insert(value);
    }
}

void print_map(const str_map& store) {
    str_map::const_iterator it = store.begin();

    while (it != store.end()) {
        pair<string, string> value = *it;
        cout << left << setw(10) << value.first << right << setw(5) << value.second << "\n";
        it++;   
    }
}

void search_map(const str_map& store, int thread_nr) {
    m.lock();
    cout << "thread(" << thread_nr << ") launched\n";
    m.unlock();

    // use a straight search or poke around random
    bool straight = false;
    if ((thread_nr % 2) == 0) {
        straight = true;
    }

    int key_nr;
    string mapped_value;
    string key;
    str_map::const_iterator it;

    string first;
    string second;

    for (unsigned int i = 0; i < MAP_SIZE; i++) {

        if (straight) {
            key_nr = i;
        } else {
            // 0 - 9999, rand is not thread-safe, nrand48 is an alternative             
            m.lock();
            key_nr = rand() % MAP_SIZE;
            m.unlock();
        }

        // convert number to string
        mapped_value = to_string(key_nr);
        key = "key_" + mapped_value;

        it = store.find(key);

        // check result
        if (it != store.end()) {
            // pair
            first = it->first;
            second = it->second;

            // m.lock();
            // cout << "thread(" << thread_nr << ") " << key << ": "
            //      << right << setw(10) << first << setw(5) << second << "\n"; 
            // m.unlock();

            // check mismatch
            if (key != first || mapped_value != second) {
                m.lock();
                cerr << key << ": " << first << second << "\n"
                     << "Mismatch in thread(" << thread_nr << ")!\n";
                exit(1);

                // never reached
                m.unlock();
            }
        } else {
            m.lock();
            cerr << "Warning: key(" << key << ") not found in thread("
                 << thread_nr << ")\n";
            exit(1);

            // never reached
            m.unlock();
        }
    }
}

int main() {
    clock_t start, end;
    start = clock();

    str_map store;
    srand(0);

    fill_map(store);
    cout << "fill_map finished\n";

    // print_map(store);
    // cout << "print_map finished\n";

    // copy for check
    str_map copy_store = store;

    // launch threads
    thread t[10];
    for (int i = 0; i < 10; i++) {
        t[i] = thread(search_map, store, i);
    }

    // wait for finish
    for (int i = 0; i < 10; i++) {
        t[i].join();
    }
    cout << "search_map threads finished\n";

    if (store == copy_store) {
        cout << "equal\n";
    } else {
        cout << "not equal\n";
    }


    end = clock();
    cout << "CLOCKS_PER_SEC " << CLOCKS_PER_SEC << "\n";
    cout << "CPU-TIME START " << start << "\n";
    cout << "CPU-TIME END " << end << "\n";
    cout << "CPU-TIME END - START " << end - start << "\n";
    cout << "TIME(SEC) " << static_cast<double>(end - start) / CLOCKS_PER_SEC << "\n";

    return 0;
}

This code can be compiled with GCC 4.7 and runs fine on my machine.

$ echo $?
$ 0

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-04T17:40:47+00:00Added an answer on June 4, 2026 at 5:40 pm

    A data-race, from the C++11 specification in sections 1.10/4 and 1.10/21, requires at least two threads with non-atomic access to the same set of memory locations, the two threads are not synchronized with regards to accessing the set of memory locations, and at least one thread writes to or modifies an element in the set of memory locations. So in your case, if the threads are only reading, you are fine … by definition since none of the threads write to the same set of memory locations, there are no data-races even though there is no explicit synchronization mechanism between the threads.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I want to access a MySQL database and I want to read+write data from+to
Using the publish_post hook, I want access to the email address of the user
I want to access a repository using both GIT and SVN clients. A way
i want to access a integer and a string from a class to all
I want to access the clipboard using Python 3.1. I've obviously come across win32clipboard,
I want to access an image stored in Blackberry, say at location store/home/user/image.png .
I want to access the text elements inside this textbox in GWT from the
Using STL, I want to find the last instance of a certain value in
What I want is something similar to STL vector when it comes to access
I want access to a picture using image.setImageResource(R.drawable.photo1); How can I change photo1 to

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.