STL & multithreading

M

mihai

What does the standard say about those two? Is any assurance that the
use of STL is thread safe?

Have a nice day,
Mihai.
 
J

James Aguilar

mihai said:
What does the standard say about those two? Is any assurance that the
use of STL is thread safe?

No, in fact, C++ has no idea what threading even is.

- JFA1
 
M

Mino Saccone

mihai said:
What does the standard say about those two? Is any assurance that the
use of STL is thread safe?

We are sure that STL is NOT thread safe

Mino Saccone
 
A

Andre Kostur

We are sure that STL is NOT thread safe

Well.... that depends:

1) The Standard makes no mention of threading, so from a Standard point of
view, this is an unanswerable question
2) That depends on _which_ implementation of STL you are talking about.
Many STL vendors do make some sort of claim about thread safety in their
products.
 
I

Ioannis Vranos

mihai said:
What does the standard say about those two? Is any assurance that the
use of STL is thread safe?

A compiler that supports multithreading, usually provides a thread-safe implementation of
the standard library. Otherwise it will state in its documentation if something is not
thread safe.
 
A

Axter

mihai said:
What does the standard say about those two? Is any assurance that the
use of STL is thread safe?

Have a nice day,
Mihai.

In general, STL objects are not thread safe.

However, it's not that hard to make them thread safe.
Check out the following link:
http://code.axter.com/ThreadSafeObject.h

The above link contains a wrapper class that can be use in Win32 code
to make STL objects thread safe.
Once the wrapper class is declared, it acts like a pointer.

Example Usage
ThreadSafeObject<vector<int> > MyThreadSafeVectorInt(new vector<int>);
MyThreadSafeVectorInt.GetLockedObject()->push_back(123);
cout << MyThreadSafeVectorInt.GetLockedObject()->at(0) << endl;

For UNIX/Linux/OS2 it would not be to hard to modify the
ThreadSafeObject wrapper class to use POSIX functions instead of Win32
API functions.

Also see following link:
http://code.axter.com/ThreadSafeViaMutexObject.h
 
P

Peter Koch Larsen

mihai said:
What does the standard say about those two? Is any assurance that the
use of STL is thread safe?

Have a nice day,
Mihai.

The *standard* has no notion of threads so it can't help you. Don't worry: I
guess most libraries that are expected to work on a multithreading platform
will provide some sort of thread-safety - you just have to look it up in the
documentation. "Standard" is for the standard library containers to be "as
safe as ints", which is the IMO correct level for safety.

/Peter
 
P

Peter Koch Larsen

Axter said:
In general, STL objects are not thread safe.

However, it's not that hard to make them thread safe.
Check out the following link:
http://code.axter.com/ThreadSafeObject.h

The above link contains a wrapper class that can be use in Win32 code
to make STL objects thread safe.
Once the wrapper class is declared, it acts like a pointer.

Example Usage
ThreadSafeObject<vector<int> > MyThreadSafeVectorInt(new vector<int>);
MyThreadSafeVectorInt.GetLockedObject()->push_back(123);
cout << MyThreadSafeVectorInt.GetLockedObject()->at(0) << endl;

For UNIX/Linux/OS2 it would not be to hard to modify the
ThreadSafeObject wrapper class to use POSIX functions instead of Win32
API functions.

Also see following link:
http://code.axter.com/ThreadSafeViaMutexObject.h

First of all, I do not see how your scheme is protecting you against a
template library that is not multithreaded. You will have problems if one of
the underlying collectionclasses access some shared variable. Secondly,
you're protecting the data at the wrong level: in general, it is not an
individual "push" operation that needs to be protected, but a larger
"logical" operation. In this common case, your protection will be at worst
useless while it in the best case only serves to eat cpu-cycles.

/Peter
 
U

Uenal Mutlu

In general, STL objects are not thread safe.

However, it's not that hard to make them thread safe.
Check out the following link:
http://code.axter.com/ThreadSafeObject.h

The above link contains a wrapper class that can be use in Win32 code
to make STL objects thread safe.
Once the wrapper class is declared, it acts like a pointer.

Example Usage
ThreadSafeObject<vector<int> > MyThreadSafeVectorInt(new vector<int>);
MyThreadSafeVectorInt.GetLockedObject()->push_back(123);
cout << MyThreadSafeVectorInt.GetLockedObject()->at(0) << endl;

This looks interessting, but have you also stress tested this using
multiple threads such like say 10 threads wanting to modify this vector?
 
A

Axter

Peter said:
First of all, I do not see how your scheme is protecting you against a
template library that is not multithreaded. You will have problems if one of
the underlying collectionclasses access some shared variable. Secondly,
you're protecting the data at the wrong level: in general, it is not an
individual "push" operation that needs to be protected, but a larger
"logical" operation. In this common case, your protection will be at worst
useless while it in the best case only serves to eat cpu-cycles.

/Peter

IMHO, you should understand the code before jumping to such false
conclusions.

Try running, and see if you can break the code.
I'm sure you'll find that it does exactly what it's suppose to do, and
it will block more then one thread from accessing the object at the
same time.

This generic code is able to make an object thread safe, because in
order to access the object, it creates a temporary object.
The temporary object does a lock in the constructor, and then does an
unlock in the temporary object's destructor.

In the future, if the code is above your head, I recommend that you try
asking questions before posting criticisms.
How can you criticize something you don't understand?
 
A

Axter

Uenal said:
This looks interessting, but have you also stress tested this using
multiple threads such like say 10 threads wanting to modify this
vector?

I've tested it with 5 threads trying to access it at the same time, and
it works great.
However, I have not tested it for performance.
 
P

Pete Becker

Axter said:
Try running, and see if you can break the code.

while (!vec.empty())
vec.pop_back();

If the code doesn't lock around the entire loop it will break. Sooner or
later you'll get a thread switch right after the call to empty returns
false, and the vector may, in fact, be empty for the call to pop_back.

As Peter said, locking containers doesn't make an application
thread-safe. And once you've added the high-level protection that's
needed to make the application thread-safe, locks in containers will
usually be redundant.
 
A

Axter

Peter said:
First of all, I do not see how your scheme is protecting you against a
template library that is not multithreaded. You will have problems if one of
the underlying collectionclasses access some shared variable. Secondly,
you're protecting the data at the wrong level: in general, it is not an
individual "push" operation that needs to be protected, but a larger
"logical" operation. In this common case, your protection will be at worst
useless while it in the best case only serves to eat cpu-cycles.

/Peter

After re-reading your comments, I think I understand your
misunderstanding.
The wrapper class I posted does not make the CLASS thread safe. The
wrapper class makes the object itself thread safe.

It prevents the object from being access at the same time from multiple
threads.

It does not stop the object from accessing another object that is not
thread safe.
So if you have an STL implementation that shares variables with
multiple instances of a class, then the wrapper class will not help.

You should be using a thread safe CLASS with the wrapper class.
 
A

Axter

Pete said:
while (!vec.empty())
vec.pop_back();

If the code doesn't lock around the entire loop it will break. Sooner or
later you'll get a thread switch right after the call to empty returns
false, and the vector may, in fact, be empty for the call to pop_back.

As Peter said, locking containers doesn't make an application
thread-safe. And once you've added the high-level protection that's
needed to make the application thread-safe, locks in containers will
usually be redundant.


Please read the entire posted thread. I'm not talking about a vector
by itself. You're above code is not using the wrapper class which is
what I was referring to in my previous post.
I'm talking about an object wrapped in the thread safe wrapper class.
See following link:
http://code.axter.com/ThreadSa­feObject.h
 
P

Pete Becker

Axter said:
I'm not talking about a vector
by itself. You're above code is not using the wrapper class which is
what I was referring to in my previous post.

The point is that with or without the wrapper class this use of the
container is not thread-safe. You need an application-level policy and
broader locking. Thread-safe containers are not sufficient, and are
usually redundant.
 
A

Andre Kostur

Please read the entire posted thread. I'm not talking about a vector
by itself. You're above code is not using the wrapper class which is
what I was referring to in my previous post.
I'm talking about an object wrapped in the thread safe wrapper class.
See following link:
http://code.axter.com/ThreadSa­feObject.h

Yes, he was talking about using your wrapper class. It was simply not
shown in the code example for brevity's sake. So to rephrase:

while (!vec.empty())
vec.pop_back();

Replace "vec." with "obj->GetLockedObject()->". So let's assume we start
with a 1000000 element vector, and we launch 100 threads with the above
code in it to clear out the vector (and for some strange reason we don't
want to just .clear() it...).

Let's continue the example that say we're down to the last element, and
25 of the threads check vec.empty() and then there's a thread context
switch right after that. The other 75 threads may be just after the
vec.pop_back(). One of the 75 gets the thread context, checks for
vec.empty() and then performs the vec.pop_back(), then context switch.
Say the remaining 74 threads are the ones that get the next contexts.
They all test vec.empty(), find the vector empty, and proceed along their
codepath. Finally those first 25 that were sitting just after the
vec.empty() call get their timeslices. All 25 will attempt a pop_back on
an empty vector. Boom. (OK, Undefined Behaviour)

Translation, your wrapper class does _not_ provide thread safety as a
silver bullet. It _only_ provides thread safety in a single atomic
operation. As soon as you need multiple operations on the object to
perform a task, you're implementation risks a context switch between the
two operations where the state of the object may be modified.
 
A

Axter

Pete said:
The point is that with or without the wrapper class this use of the
container is not thread-safe. You need an application-level policy and
broader locking. Thread-safe containers are not sufficient, and are
usually redundant.

Can you prove that point with some type of example code that would
break?
And I'm not referring to a class that shares objects with multiple
instances of the class.
I'm referring to a typical class that has no shared objects.
Show me how a class like that would break using a thread-safe wrapper
class.
 
P

Pete Becker

Axter said:
Can you prove that point with some type of example code that would
break?

I gave you an example and I explained it. Do you have questions about
that example?
 
I

Ioannis Vranos

Pete said:
The point is that with or without the wrapper class this use of the
container is not thread-safe. You need an application-level policy and
broader locking. Thread-safe containers are not sufficient, and are
usually redundant.


With wrapper classes aside, do you think that there are not multithreading-enabled STL
implementations? I am not sure what you mean with the redundant part too.

But first let's define what we mean with "thread-safety". I assume we are talking about
different threads accessing safely different parts of a container (like a vector) and
calling a given function concurrently, right?
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,202
Messages
2,571,057
Members
47,666
Latest member
selsetu

Latest Threads

Top