- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
I have some questions about the use of mutexes.
1) Having this code, is it safe to concurrently invoke the method DoObject from the global resource in each child task to modify the state of the local objects? I have tried it several times and ended always getting the expected result. However, can the program in some run yield and incorrect result since the resource is not protected by a mutex? Isn't threre a data race that can corrupt the state of the objects?
Here?:
or here?:
Thanks in advance.
I have some questions about the use of mutexes.
1) Having this code, is it safe to concurrently invoke the method DoObject from the global resource in each child task to modify the state of the local objects? I have tried it several times and ended always getting the expected result. However, can the program in some run yield and incorrect result since the resource is not protected by a mutex? Isn't threre a data race that can corrupt the state of the objects?
[cpp]class Resource { public: Resource(){} void DoObject(MyObject* o) { o->AddX( o->GetY() ); o->AddY( o->GetX() ); } } class MyObject{ private: int x; int y; public: MyObject( ... ):...{} // getters and setters here } class Child: public tbb::task { private: Myobject* local_object; Resource* global_resource public: Child(...):...{} tbb::task* execute() { global_resource->DoObject( local_object );2) If a mutex is needed, where is the most appropiate place to put it.
return NULL;
} } class Root: public tbb::task { // spawn several child tasks, i.e. 2 } int main() { Resource* res = new Resource; MyObject* o1 = new Object( ... ); MyObject* o2 = new Object( ... ); Root& r = *new(tbb::task::allocate_root()) Root( o1, o2, res ); tbb::task::spawn_root_and_wait( r ); }[/cpp]
Here?:
[cpp]typedef tbb::spin_mutex MutexType; class Resource { private: /// more things MutexType Mutex; public: /// more things void DoObject(MyObject* o) { MutexType::scoped_lock lock( Mutex ); /// do the work } }[/cpp]
or here?:
[cpp]typedef tbb::spin_mutex MutexType; class Resource { private: /// more things MutexType Mutex; public: /// more things void DoObject(MyObject* o){ /// do the work as always } MutexType& GetMutex() const { return Mutex; } }; class Child: public tbb::task { /// more things Resource* global_resource; public: /// more things tbb::task* execute() { MutexType::scoped_lock lock( global_resource->GetMutex() ); global_resource->DoObject( local_object ); return NULL; } };[/cpp]
Thanks in advance.
Link Copied
6 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
In the example provided, DoObject only affects the specified object. By placing the mutex within the object, multiple different objects can be locked and worked on simultaneously. A global resource lock may also be required for other functions that manage multiple (all) objects in one session. You also might want to consider having DoObject not lock and providing DoObjectWithLock that does:
lock, DoObject(p1), unlock
or
global lock, DoObject(p1), DoObject(p2), DoObject(pn), global unlock
Jim Dempsey
lock, DoObject(p1), unlock
or
global lock, DoObject(p1), DoObject(p2), DoObject(pn), global unlock
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
thanks for your answer Jim.
"By placing the mutex within the object"
Do you mean having a mutex as a private member of the class, like in Resource?
"multiple different objects can be locked and worked on simultaneously"
So multiple Resources could be working simultaneosly, is that?
But if there is something like this:
Or do you mean something like:
"A global resource lock may also be required"
Like this?
Sorry about my questions but I find kinda difficult this topic.
Thanks.
thanks for your answer Jim.
"By placing the mutex within the object"
Do you mean having a mutex as a private member of the class, like in Resource?
"multiple different objects can be locked and worked on simultaneously"
So multiple Resources could be working simultaneosly, is that?
But if there is something like this:
[cpp]Resource* res = new Resource; std::vectorThis should be ok with and without a mutex, as you stated in your answer.v; // fill vector with pointers for(unsigned int i(0); i DoObject( v.at(i) ); }
[/cpp]
Or do you mean something like:
[bash]class MyObject { private: MutexType Mutex; public: /// };[/bash]
"A global resource lock may also be required"
Like this?
[cpp]typedef tbb::spin_mutex MutexType; MutexType GlobalMutex; class ... { /// more things }; class ... { /// more things }; [/cpp]Or declared in, for example, a header file that will be included by others?
Sorry about my questions but I find kinda difficult this topic.
Thanks.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
When processing a single vector of object pointers as outlined in the first example you need not have locks within the objects as long as only one such object is processed by any one thread at any one time. Note, a parallel_for would work on different slices of the vector and concurrent work would be fine as long as noobjectis worked onconcurrently by two threads witout lock or other protection (e.g. atomic update). An example of this could be a vector of objects interacting via gravity or charge where the parallel_for of a subset of the vector upon a secondary reference to thevector would introduce concurrent updates to objects. In these cases either use object mutex or zone exclusions without mutex.
The purpose of the mutex is to avoid something like
A = A + X
Where the operation is concurrent with multiple threads .AND. not performed atomicly or within a protected critical section (locked by mutex).
If you can avoid mutex and be thread safe, please do so as it generaly offers better performance.
Jim Dempsey
The purpose of the mutex is to avoid something like
A = A + X
Where the operation is concurrent with multiple threads .AND. not performed atomicly or within a protected critical section (locked by mutex).
If you can avoid mutex and be thread safe, please do so as it generaly offers better performance.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi!
Thanks for your answers, Jim.
This is the last question!
While searching the forums I found this: http://software.intel.com/en-us/forums/showthread.php?t=64849&o=a&s=lr
In the code of Anton's answer(http://software.intel.com/en-us/forums/showpost.php?p=82360), the mutex is declared as public. Is there a special reason for that? If I declare the mutex as private and have a function like
And, why the static keyword?
Thanks!!
Thanks for your answers, Jim.
This is the last question!
While searching the forums I found this: http://software.intel.com/en-us/forums/showthread.php?t=64849&o=a&s=lr
In the code of Anton's answer(http://software.intel.com/en-us/forums/showpost.php?p=82360), the mutex is declared as public. Is there a special reason for that? If I declare the mutex as private and have a function like
[cpp]CurrentMutexType& GetMutex(void) const { return currentMutex; }[/cpp]wouldn't that work as well?
And, why the static keyword?
Thanks!!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
If I may step in while Jim has nighttime in his timezone, GetMutex() would work as well but seems a bit pedantic, and that particular mutex is static because it is not about protecting instances of A but about concurrent access to std::cout across instances of A (in addition to the possibly concurrent use of the operator per instance).
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thank you Raf!!
Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page