Asynchronous call implementation

Discussion in 'Microsoft C# .NET' started by archana, Sep 5, 2012.

  1. archana

    archana Guest

    Hi all,

    Need some suggestion on implementating locking mechanism.
    currently i have multple asynchronous request which have one callback
    function. In callback , i am traverssing through dictionary and adding
    into some shared dictionary, Callback is shared accross multiple
    thread. So to prevent more than one thread trying to add to sharred
    dictionary i have enclosed in lock statement.

    But I am thinking of removing lock statment from entire callback and
    adding lock statment only when looking into shared resource and adding
    to shared resource.

    My query is will it cause any issue if more than one thread try to
    look into dictionary and try to add same value at the same time to
    dictionary.

    Can anyone please shed some light on this/

    thanks in advance.
     
    archana, Sep 5, 2012
    #1
    1. Advertisements

  2. archana

    Brian Cryer Guest

    "archana" <> wrote in message
    news:...
    > Hi all,
    >
    > Need some suggestion on implementating locking mechanism.
    > currently i have multple asynchronous request which have one callback
    > function. In callback , i am traverssing through dictionary and adding
    > into some shared dictionary, Callback is shared accross multiple
    > thread. So to prevent more than one thread trying to add to sharred
    > dictionary i have enclosed in lock statement.
    >
    > But I am thinking of removing lock statment from entire callback and
    > adding lock statment only when looking into shared resource and adding
    > to shared resource.
    >
    > My query is will it cause any issue if more than one thread try to
    > look into dictionary and try to add same value at the same time to
    > dictionary.
    >
    > Can anyone please shed some light on this/
    >
    > thanks in advance.


    Short answer: Yes it will cause issues, so keep it as it is.

    Longer answer:

    I don't know the internal implementation of a dictionary, but I would
    *assume* that any lookup won't change the structure, and if this assumption
    is correct then if all you were doing were lookups then you wouldn't need to
    lock the dictionary and it should be thread-safe. I think this is a
    reasonable assumption, but it is still an assumption.

    BUT you are also adding. When you add it will change the structure, and this
    certaily isn't thread safe. It will cause problems for any other threads
    that are accessing the dictionary - including those which are just reading.
    So if you just lock for updates but not reads, then your threads which are
    reading will eventually break and throw an exception. So you need to keep it
    locked for all accesses.

    If say the majority of your accesses were reads and updates are infrequent,
    then you could look into a locking strategy which allowed parallel reads but
    blocked everything on a write. That would require a bit of thought.
    Something like: using semaphores (have lots) to control access to the
    dictionary, a mutex to only allow one update at a time and the thread which
    has the write mutex can then only do the update once it has successfully
    been able to grab ALL of the semaphores. This is adding complexity, so
    unless you are finding this to be a performance block then I wouldn't
    bother.

    Hope this helps.
    --
    Brian Cryer
    http://www.cryer.co.uk/brian
     
    Brian Cryer, Sep 5, 2012
    #2
    1. Advertisements

  3. On 05.09.12 11.14, Brian Cryer wrote:
    > I don't know the internal implementation of a dictionary, but I would
    > *assume* that any lookup won't change the structure, and if this
    > assumption is correct then if all you were doing were lookups then you
    > wouldn't need to lock the dictionary and it should be thread-safe. I
    > think this is a reasonable assumption, but it is still an assumption.


    AFAIK the .NET collections are thread safe for read-only access. But as
    soon as there might be one writer, read is no longer safe.


    > If say the majority of your accesses were reads and updates are
    > infrequent, then you could look into a locking strategy which allowed
    > parallel reads but blocked everything on a write. That would require a
    > bit of thought. Something like: using semaphores (have lots) to control
    > access to the dictionary, a mutex to only allow one update at a time and
    > the thread which has the write mutex can then only do the update once it
    > has successfully been able to grab ALL of the semaphores. This is adding
    > complexity, so unless you are finding this to be a performance block
    > then I wouldn't bother.


    ? - ReaderWriterLockSlim will do the job.

    However, in case of infrequent updates and a not too large dictionary
    there is an even more simple solution. Lock only the writers and do the
    following steps in the critical section:
    - copy the dictionary
    - modify the local copy
    - replace the global reference to the current dictionary with the local
    copy.
    From that on the now shared dictionary instance is immutable and
    therefore thread safe. And changing the value of a reference is
    implicitly thread safe in .NET.

    This solution requires no locking for readers at all.


    Marcel
     
    Marcel Müller, Sep 5, 2012
    #3
  4. archana

    Arne Vajhøj Guest

    On 9/5/2012 3:04 AM, archana wrote:
    > Need some suggestion on implementating locking mechanism.
    > currently i have multple asynchronous request which have one callback
    > function. In callback , i am traverssing through dictionary and adding
    > into some shared dictionary, Callback is shared accross multiple
    > thread. So to prevent more than one thread trying to add to sharred
    > dictionary i have enclosed in lock statement.
    >
    > But I am thinking of removing lock statment from entire callback and
    > adding lock statment only when looking into shared resource and adding
    > to shared resource.
    >
    > My query is will it cause any issue if more than one thread try to
    > look into dictionary and try to add same value at the same time to
    > dictionary.
    >
    > Can anyone please shed some light on this/


    1)

    There are some single operation issues that you need to
    handle correctly:
    * avoid corruption of data structure when multiple threads
    update the data structure
    * avoid inconsistent results when one thread read data structure
    being updated by another thread
    * having updates to data structure being visible to other threads
    (and not be in some CPU specific write back cache)

    By far the easiest way of handling those are by using lock.

    2)

    On top of that there may be some multi operation issues that you
    also need to handle correct:
    * avoid something relevant happening between two operations

    This is also best handled by using lock.

    3)

    For best performance you should lock the minimum code sequence
    as possible.

    For single operation just the single call.

    For multi operation from before the first call to after the
    last call.

    Arne
     
    Arne Vajhøj, Sep 6, 2012
    #4
  5. archana

    Arne Vajhøj Guest

    On 9/5/2012 3:27 PM, Marcel Müller wrote:
    > However, in case of infrequent updates and a not too large dictionary
    > there is an even more simple solution. Lock only the writers and do the
    > following steps in the critical section:
    > - copy the dictionary
    > - modify the local copy
    > - replace the global reference to the current dictionary with the local
    > copy.
    > From that on the now shared dictionary instance is immutable and
    > therefore thread safe. And changing the value of a reference is
    > implicitly thread safe in .NET.
    >
    > This solution requires no locking for readers at all.


    I don't see how that guarantees that updates are visible to
    other treads.

    Arne
     
    Arne Vajhøj, Sep 6, 2012
    #5
  6. archana

    Arne Vajhøj Guest

    On 9/5/2012 5:14 AM, Brian Cryer wrote:
    > "archana" <> wrote in message
    > news:...
    >> But I am thinking of removing lock statment from entire callback and
    >> adding lock statment only when looking into shared resource and adding
    >> to shared resource.
    >>
    >> My query is will it cause any issue if more than one thread try to
    >> look into dictionary and try to add same value at the same time to
    >> dictionary.
    >>
    >> Can anyone please shed some light on this/
    >>
    >> thanks in advance.

    >
    > Short answer: Yes it will cause issues


    Not necessarily.

    > , so keep it as it is.
    >
    > Longer answer:
    >
    > I don't know the internal implementation of a dictionary, but I would
    > *assume* that any lookup won't change the structure, and if this
    > assumption is correct then if all you were doing were lookups then you
    > wouldn't need to lock the dictionary and it should be thread-safe. I
    > think this is a reasonable assumption, but it is still an assumption.
    >
    > BUT you are also adding. When you add it will change the structure, and
    > this certaily isn't thread safe. It will cause problems for any other
    > threads that are accessing the dictionary - including those which are
    > just reading. So if you just lock for updates but not reads, then your
    > threads which are reading will eventually break and throw an exception.
    > So you need to keep it locked for all accesses.


    That is all correct, but it seems as if the alternatives being compared are:
    - lock entire callback
    - just lock Dictionary read and write (but both)

    Arne
     
    Arne Vajhøj, Sep 6, 2012
    #6
  7. archana

    Brian Cryer Guest

    "Marcel Müller" <> wrote in message
    news:5047a7b7$0$6570$-online.net...
    > On 05.09.12 11.14, Brian Cryer wrote:
    >> I don't know the internal implementation of a dictionary, but I would
    >> *assume* that any lookup won't change the structure, and if this
    >> assumption is correct then if all you were doing were lookups then you
    >> wouldn't need to lock the dictionary and it should be thread-safe. I
    >> think this is a reasonable assumption, but it is still an assumption.

    >
    > AFAIK the .NET collections are thread safe for read-only access. But as
    > soon as there might be one writer, read is no longer safe.
    >
    >
    >> If say the majority of your accesses were reads and updates are
    >> infrequent, then you could look into a locking strategy which allowed
    >> parallel reads but blocked everything on a write. That would require a
    >> bit of thought. Something like: using semaphores (have lots) to control
    >> access to the dictionary, a mutex to only allow one update at a time and
    >> the thread which has the write mutex can then only do the update once it
    >> has successfully been able to grab ALL of the semaphores. This is adding
    >> complexity, so unless you are finding this to be a performance block
    >> then I wouldn't bother.

    >
    > ? - ReaderWriterLockSlim will do the job.


    I wasn't aware of ReaderWriterLockSlim. Thank you.

    --
    Brian Cryer
    http://www.cryer.co.uk/brian
     
    Brian Cryer, Sep 6, 2012
    #7
  8. archana

    Brian Cryer Guest

    "Arne Vajhøj" <> wrote in message
    news:50480bf6$0$293$...
    > On 9/5/2012 5:14 AM, Brian Cryer wrote:
    >> "archana" <> wrote in message
    >> news:...
    >>> But I am thinking of removing lock statment from entire callback and
    >>> adding lock statment only when looking into shared resource and adding
    >>> to shared resource.
    >>>
    >>> My query is will it cause any issue if more than one thread try to
    >>> look into dictionary and try to add same value at the same time to
    >>> dictionary.
    >>>
    >>> Can anyone please shed some light on this/
    >>>
    >>> thanks in advance.

    >>
    >> Short answer: Yes it will cause issues

    >
    > Not necessarily.


    I agree that there is always a chance that you'd get away with it, but I
    don't think that trusting to luck is a sensible approach because eventually
    it will break - the only question is how long it will go before breaking and
    how repeatable it is. So I think my original short answer was correct: "Yes
    it will cause issues, so keep it as it is" - i.e. keep locking in place.

    <snip>

    > That is all correct, but it seems as if the alternatives being compared
    > are:
    > - lock entire callback
    > - just lock Dictionary read and write (but both)


    If it were me then I'd go with Marcel's suggestion of using
    ReaderWriterLockSlim.
    --
    Brian Cryer
    http://www.cryer.co.uk/brian
     
    Brian Cryer, Sep 6, 2012
    #8
  9. On Wed, 5 Sep 2012 00:04:18 -0700 (PDT), archana <>
    wrote:

    >Hi all,
    >
    >Need some suggestion on implementating locking mechanism.
    >currently i have multple asynchronous request which have one callback
    >function. In callback , i am traverssing through dictionary and adding
    >into some shared dictionary, Callback is shared accross multiple
    >thread. So to prevent more than one thread trying to add to sharred
    >dictionary i have enclosed in lock statement.
    >
    >But I am thinking of removing lock statment from entire callback and
    >adding lock statment only when looking into shared resource and adding
    >to shared resource.
    >

    In .NET 4 the System.Collections.Concurrent namespace contains several
    thread-safe data structures.
    <http://msdn.microsoft.com/en-us/library/system.collections.concurrent.aspx>
    http://msdn.microsoft.com/en-us/library/system.collections.concurrent.aspx

    regards
    A.G.
     
    Registered User, Sep 6, 2012
    #9
  10. On 06.09.2012 04:32, Arne Vajhøj wrote:
    > I don't see how that guarantees that updates are visible to
    > other treads.


    It doesn't, but as long as other threads do not synchronize otherwise to
    the changing thread, it makes no difference. It is just as if the other
    thread has been some more ahead in time.

    And in practice it simply works, since incoherent caches are not that
    common.


    Marcel
     
    Marcel Müller, Sep 6, 2012
    #10
  11. archana

    Arne Vajhøj Guest

    On 9/6/2012 8:22 AM, Registered User wrote:
    > On Wed, 5 Sep 2012 00:04:18 -0700 (PDT), archana <>
    > wrote:
    >> Need some suggestion on implementating locking mechanism.
    >> currently i have multple asynchronous request which have one callback
    >> function. In callback , i am traverssing through dictionary and adding
    >> into some shared dictionary, Callback is shared accross multiple
    >> thread. So to prevent more than one thread trying to add to sharred
    >> dictionary i have enclosed in lock statement.
    >>
    >> But I am thinking of removing lock statment from entire callback and
    >> adding lock statment only when looking into shared resource and adding
    >> to shared resource.
    >>

    > In .NET 4 the System.Collections.Concurrent namespace contains several
    > thread-safe data structures.
    > <http://msdn.microsoft.com/en-us/library/system.collections.concurrent.aspx>
    > http://msdn.microsoft.com/en-us/library/system.collections.concurrent.aspx


    Note that thread safe here is used in the traditional meaning: thread
    safe for single operations.

    In some multi operations scenarios explicit locking is still
    necessary.

    Arne
     
    Arne Vajhøj, Sep 7, 2012
    #11
  12. archana

    Arne Vajhøj Guest

    On 9/6/2012 1:48 PM, Marcel Müller wrote:
    > On 06.09.2012 04:32, Arne Vajhøj wrote:
    >> I don't see how that guarantees that updates are visible to
    >> other treads.

    >
    > It doesn't, but as long as other threads do not synchronize otherwise to
    > the changing thread, it makes no difference. It is just as if the other
    > thread has been some more ahead in time.


    The updates must be used by something - otherwise there are no reason
    to do them at all.

    So something should be missing them.

    > And in practice it simply works, since incoherent caches are not that
    > common.


    "not that common" is not a good reason to write code with
    concurrency bugs in.

    Arne
     
    Arne Vajhøj, Sep 7, 2012
    #12
  13. archana

    Arne Vajhøj Guest

    On 9/6/2012 5:21 AM, Brian Cryer wrote:
    > "Arne Vajhøj" <> wrote in message
    > news:50480bf6$0$293$...
    >> On 9/5/2012 5:14 AM, Brian Cryer wrote:
    >>> "archana" <> wrote in message
    >>> news:...
    >>>
    >>>> But I am thinking of removing lock statment from entire callback and
    >>>> adding lock statment only when looking into shared resource and adding
    >>>> to shared resource.
    >>>>
    >>>> My query is will it cause any issue if more than one thread try to
    >>>> look into dictionary and try to add same value at the same time to
    >>>> dictionary.
    >>>>
    >>>> Can anyone please shed some light on this/
    >>>>
    >>>> thanks in advance.
    >>>
    >>> Short answer: Yes it will cause issues

    >>
    >> Not necessarily.

    >
    > I agree that there is always a chance that you'd get away with it, but I
    > don't think that trusting to luck is a sensible approach because
    > eventually it will break - the only question is how long it will go
    > before breaking and how repeatable it is. So I think my original short
    > answer was correct: "Yes it will cause issues, so keep it as it is" -
    > i.e. keep locking in place.


    No.

    The problem is:

    #But I am thinking of removing lock statment from entire callback and
    #adding lock statment only when looking into shared resource and adding
    #to shared resource.

    So he now has code like:

    rettype callback()
    {
    lock(somelockobject)
    {
    foobar();
    firstsharedobject.dosomething();
    barfoo();
    secondsharedobject.dosomething();
    foobarfoobar();
    }
    }

    and are considering either:

    rettype callback()
    {
    foobar();
    lock(somelockobject)
    {
    firstsharedobject.dosomething();
    barfoo();
    secondsharedobject.dosomething();
    }
    foobarfoobar();
    }

    or:

    rettype callback()
    {
    foobar();
    lock(somelockobject)
    {
    firstsharedobject.dosomething();
    }
    barfoo();
    lock(somelockobject)
    {
    secondsharedobject.dosomething();
    }
    foobarfoobar();
    }

    The first is perfectly threadsafe.

    The second is perfectly thread safe in single operation perspective
    (and that is unfortunately the traditional meaning of thread safe),
    but not thread safe in multi operation context.

    So the code may be fine.

    Arne
     
    Arne Vajhøj, Sep 7, 2012
    #13
  14. On 06.09.12 14.22, Registered User wrote:
    > In .NET 4 the System.Collections.Concurrent namespace contains several
    > thread-safe data structures.
    > <http://msdn.microsoft.com/en-us/library/system.collections.concurrent.aspx>


    Well, these are AFAIR mainly lock-free data structures. This might be
    state of the art, but especially the ConcurrentDictionary is not that
    trivial to implement that way. And in fact it is slower than an ordinary
    dictionary with an ordinary lock in most cases. Unfortunately I did not
    bookmark the link to the article where this was tested.
    Note that this applies to .NET 4.0. The .NET 4.5 implementations have
    been improved.


    Marcel
     
    Marcel Müller, Sep 9, 2012
    #14
  15. archana

    Arne Vajhøj Guest

    On 9/9/2012 3:15 AM, Marcel Müller wrote:
    > On 06.09.12 14.22, Registered User wrote:
    >> In .NET 4 the System.Collections.Concurrent namespace contains several
    >> thread-safe data structures.
    >> <http://msdn.microsoft.com/en-us/library/system.collections.concurrent.aspx>

    >
    > Well, these are AFAIR mainly lock-free data structures. This might be
    > state of the art, but especially the ConcurrentDictionary is not that
    > trivial to implement that way. And in fact it is slower than an ordinary
    > dictionary with an ordinary lock in most cases. Unfortunately I did not
    > bookmark the link to the article where this was tested.
    > Note that this applies to .NET 4.0. The .NET 4.5 implementations have
    > been improved.


    And it is still single operation integrity.

    Often multi operation integrity is what one needs.

    Constructs like:

    if(mylist.Count > 0)
    {
    X o = mylist[0];
    mylist.RemoveAt(0);
    ...
    }

    and:

    mydict[key] = mydict[key] + 1;

    Arne
     
    Arne Vajhøj, Sep 10, 2012
    #15
  16. On 10.09.2012 03:41, Arne Vajhøj wrote:
    [ConcurrentHashMap]
    > And it is still single operation integrity.
    >
    > Often multi operation integrity is what one needs.
    >
    > Constructs like:
    >
    > if(mylist.Count > 0)
    > {
    > X o = mylist[0];
    > mylist.RemoveAt(0);


    You wont get that happy with RemoveAt in a hash table. ;-)

    > ...
    > }
    >
    > and:
    >
    > mydict[key] = mydict[key] + 1;


    Well, the interface is a bit more sophisticated:

    X o;
    if (mylist.TryRemove(key, out o))
    { ...
    }

    mylist.AddOrUpdate(key, k => throw new KeyNotFoundException(), (k,v) =>
    v+1);


    Marcel
     
    Marcel Müller, Sep 11, 2012
    #16
    1. Advertisements

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. wobbles

    strange problem with Asynchronous call

    wobbles, Jan 7, 2004, in forum: Microsoft C# .NET
    Replies:
    4
    Views:
    161
    wobbles
    Jan 7, 2004
  2. Justin Harrison

    Asynchronous call problem

    Justin Harrison, Feb 13, 2004, in forum: Microsoft C# .NET
    Replies:
    2
    Views:
    185
    James
    Feb 14, 2004
  3. Ollie
    Replies:
    1
    Views:
    1,878
    Ollie
    Mar 19, 2004
  4. Kerem Gümrükcü

    Passing COM Interface Implementation to PInvoke API Call,...

    Kerem Gümrükcü, Sep 26, 2008, in forum: Microsoft C# .NET
    Replies:
    4
    Views:
    185
    Kerem Gümrükcü
    Oct 2, 2008
  5. John Rivers

    how to call base implementation of method from base

    John Rivers, Oct 12, 2010, in forum: Microsoft C# .NET
    Replies:
    2
    Views:
    367
    John Rivers
    Oct 17, 2010
Loading...

Share This Page