deletion of objects problem - multi-threaded program

A

Angus

Hi

I have written a program which runs two threads. One thread controls
the creation and modification of an object used in the program.
Another thread periodically checks a list of these objects and deletes
an object from the list if no longer required.

I have written a class to wrap the operating system specific lock /
unlock of the object. This works fine. But I get the following
problem:

1. thread 1 creates object1.

2. thread 2 checks object1 to see if ready for deletion and it
eroneously considers it is.

3. thread 1 modifies object1.

4. (simultaneously with 3.) deletes object1.

Result is an access violation as at 3. a pointer to object1 is
dereferenced.


My possible solutions for this problem are:

1. Add a lock and unlock function to the object1 class. Then have to
lock, perform manipulation, then unlock. But then if a instruction
was waiting for the access control/critical section to free up and the
object gets deleted - then what happens?

2. Don't actually delete object1. Simply mark it as deletable. then
have another thread check when possible to delete object1 say every
hour - when there is no chance that thread1 would be doing anything
with object1.

Noe of these solutions seems ideal. Or maybe I am not understanding
correctly.

Does anyone have any suggestions?

Angus
 
M

Marcel Müller

Hi,
1. thread 1 creates object1.

2. thread 2 checks object1 to see if ready for deletion and it
eroneously considers it is.

why? Thread 2 must not do this mistake.
3. thread 1 modifies object1.

4. (simultaneously with 3.) deletes object1.

Result is an access violation as at 3. a pointer to object1 is
dereferenced.
Obviously.


My possible solutions for this problem are:

1. Add a lock and unlock function to the object1 class. Then have to
lock, perform manipulation, then unlock. But then if a instruction
was waiting for the access control/critical section to free up and the
object gets deleted - then what happens?

A lock won't solve your problem. (It might solve other concurrency issues.)

2. Don't actually delete object1. Simply mark it as deletable. then
have another thread check when possible to delete object1 say every
hour - when there is no chance that thread1 would be doing anything
with object1.

The expression 'no chance' has no meaning for concurrency issues. So
don't rely on that. Although think what happens if all objects that your
application uses reside in memory for at least one hour. Depending on
you application this might be a serious problem.

Noe of these solutions seems ideal.

True. You need thread 1 to tell when it does no longer need the object.
The easiest solution is to use reference counting. And the strongly
recommended way to do so is to use smart pointers. Have a look at
boost::shared_ptr or boost::intrusive_ptr. Once you use them
consequently you might not need thread 2 at all, because it is straight
forward when the object is no longer needed. This is exactly when no
(smart) pointer to the object exists. In this case you cannot access the
object anymore because you don't know where it lies in memory.
The smart pointer will automatically delete your object if the last
reference has gone. For this to work, you must not hold any ordinary
pointers or references to object. Exception: if you are absolutely sure
that a longer lived smart pointer instance points to the same object the
whole time.


Marcel
 
M

Maxim Yegorushkin

Hi,


why? Thread 2 must not do this mistake.


A lock won't solve your problem. (It might solve other concurrency issues.)



The expression 'no chance' has no meaning for concurrency issues. So
don't rely on that. Although think what happens if all objects that your
application uses reside in memory for at least one hour. Depending on
you application this might be a serious problem.



True. You need thread 1 to tell when it does no longer need the object.
The easiest solution is to use reference counting. And the strongly
recommended way to do so is to use smart pointers. Have a look at
boost::shared_ptr or boost::intrusive_ptr. Once you use them
consequently you might not need thread 2 at all, because it is straight
forward when the object is no longer needed. This is exactly when no
(smart) pointer to the object exists. In this case you cannot access the
object anymore because you don't know where it lies in memory.
The smart pointer will automatically delete your object if the last
reference has gone. For this to work, you must not hold any ordinary
pointers or references to object. Exception: if you are absolutely sure
that a longer lived smart pointer instance points to the same object the
whole time.

Agree, reference counting solve this issue easily.

I once worked on a mature multithreaded system where people did not
heard about smart-pointers or reference counting. They had exactly the
same problem when threads shared objects and could not destroy them
orderly. They came up with a reaper thread whose sole purpose was to
destroy objects. And it worked about 99% of the time, since with no
reference counters race conditions were still present that would crash
the application or make it use corrupted objects.
 
C

Chris M. Thomasson

Angus said:
Hi

I have written a program which runs two threads. One thread controls
the creation and modification of an object used in the program.
Another thread periodically checks a list of these objects and deletes
an object from the list if no longer required.

I have written a class to wrap the operating system specific lock /
unlock of the object. This works fine. But I get the following
problem: [...]
My possible solutions for this problem are:

1. Add a lock and unlock function to the object1 class. Then have to
lock, perform manipulation, then unlock. But then if a instruction
was waiting for the access control/critical section to free up and the
object gets deleted - then what happens?

Hopefully it will seg-fault ASAP and not corrupt anything!

;^o



2. Don't actually delete object1. Simply mark it as deletable. then
have another thread check when possible to delete object1 say every
hour - when there is no chance that thread1 would be doing anything
with object1.

Why not have the thread which "marks it" actually delete it? What's this
other thread going to do anyway? What type of "post-processing" do
"to-be-deleted" objects require?



Noe of these solutions seems ideal. Or maybe I am not understanding
correctly.

Does anyone have any suggestions?

I need more information. However, for now, why not have Thread 1 put object
than can be deleted into a queue which is consumed by Thread 2? Thread 2
just waits on that queue and any objects which come through are quiescent
wrt Thread 1? When you mark an object as "deletable", is said object truly
in a persistent quiescent state??? This is important...
 
C

Chris M. Thomasson

[...]
I once worked on a mature multithreaded system where people did not heard
about smart-pointers or reference counting. They had exactly the same
problem when threads shared objects and could not destroy them orderly.
They came up with a reaper thread whose sole purpose was to destroy
objects. And it worked about 99% of the time, since with no reference
counters race conditions were still present that would crash the
application or make it use corrupted objects.

FWIW, IMHO traditional reference counting can be "overkill" for many
problems. Sometimes you just know when a part of you're application is in a
quiescent state.

;^)
 
B

Brian Wood

There is no need for the third thread.  Define what it is that indicates
that the object is deletable, then only set that indicator in thread 1
and only check that indicator (and actually delete the object) in thread
2.  Before that indicator is set, the object is alive.  Setting of the
indicator and checking it should be atomic.

This is probably clear to some, but I will add a note on that
last sentence. I think he's saying that setting of the
indicator should be atomic. Likewise checking the indicator
should be atomic.


Brian Wood
http://www.webEbenezer.net
 

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

No members online now.

Forum statistics

Threads
473,982
Messages
2,570,190
Members
46,736
Latest member
zacharyharris

Latest Threads

Top