deletion of objects problem - multi-threaded program

Discussion in 'C++' started by Angus, Nov 6, 2009.

  1. Angus

    Angus Guest

    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
     
    Angus, Nov 6, 2009
    #1
    1. Advertising

  2. Hi,

    Angus wrote:
    > 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
     
    Marcel Müller, Nov 7, 2009
    #2
    1. Advertising

  3. On 07/11/09 11:45, Marcel Müller wrote:
    > Hi,
    >
    > Angus wrote:
    >> 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.


    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.

    --
    Max
     
    Maxim Yegorushkin, Nov 7, 2009
    #3
  4. "Angus" <> wrote in message
    news:...
    > 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...
     
    Chris M. Thomasson, Nov 7, 2009
    #4
  5. "Maxim Yegorushkin" <> wrote in message
    news:4af57231$0$9752$...
    [...]
    > 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.

    ;^)
     
    Chris M. Thomasson, Nov 7, 2009
    #5
  6. Angus

    Brian Wood Guest

    On Nov 6, 9:55 am, Victor Bazarov <> wrote:

    > 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
     
    Brian Wood, Nov 8, 2009
    #6
    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. ian douglas
    Replies:
    2
    Views:
    988
    Randy Howard
    Jul 30, 2004
  2. Nasif
    Replies:
    6
    Views:
    323
    Sani Rus
    Oct 9, 2008
  3. Nasif

    Testing Multi Threaded program on linux

    Nasif, Sep 18, 2008, in forum: C Programming
    Replies:
    7
    Views:
    364
    Antoninus Twink
    Oct 9, 2008
  4. C++Liliput
    Replies:
    3
    Views:
    438
    James Kanze
    Sep 24, 2008
  5. mk
    Replies:
    1
    Views:
    301
    Jonathan Hartley
    Dec 30, 2009
Loading...

Share This Page