Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.java.programmer > #30966 > unrolled thread

Concurrency question?

Started byKnute Johnson <nospam@rabbitbrush.frazmtn.com>
First post2015-01-31 10:34 -0800
Last post2015-02-16 06:32 -0800
Articles 17 — 10 participants

Back to article view | Back to comp.lang.java.programmer


Contents

  Concurrency question? Knute Johnson <nospam@rabbitbrush.frazmtn.com> - 2015-01-31 10:34 -0800
    Re: Concurrency question? Eric Sosman <esosman@comcast-dot-net.invalid> - 2015-01-31 14:04 -0500
      Re: Concurrency question? Knute Johnson <nospam@rabbitbrush.frazmtn.com> - 2015-01-31 11:23 -0800
    Re: Concurrency question? Arne Vajhøj <arne@vajhoej.dk> - 2015-01-31 14:12 -0500
      Re: Concurrency question? Knute Johnson <nospam@rabbitbrush.frazmtn.com> - 2015-01-31 11:33 -0800
    Re: Concurrency question? v_borchert@despammed.com (Volker Borchert) - 2015-01-31 19:20 +0000
      Re: Concurrency question? Eric Sosman <esosman@comcast-dot-net.invalid> - 2015-01-31 15:42 -0500
        Re: Concurrency question? Knute Johnson <eternal@knutejohnson.com> - 2015-01-31 19:51 -0800
          Re: Concurrency question? Eric Sosman <esosman@comcast-dot-net.invalid> - 2015-02-01 09:24 -0500
    Re: Concurrency question? Kevin McMurtrie <mcmurtrie@pixelmemory.us> - 2015-01-31 22:59 -0800
      Re: Concurrency question? Arne Vajhøj <arne@vajhoej.dk> - 2015-02-01 12:55 -0500
        Re: Concurrency question? Silvio <silvio@internet.com> - 2015-02-01 22:19 +0100
        Re: Concurrency question? Kevin McMurtrie <mcmurtrie@pixelmemory.us> - 2015-02-06 22:29 -0800
          Re: Concurrency question? Knute Johnson <eternal@knutejohnson.com> - 2015-02-07 10:14 -0800
          Re: Concurrency question? Robert Klemme <shortcutter@googlemail.com> - 2015-02-08 19:33 +0100
    Re: Concurrency question? olupot douglas <olupotd3@gmail.com> - 2015-02-07 01:06 -0800
    Re: Concurrency question? Haddock <ffm2002@web.de> - 2015-02-16 06:32 -0800

#30966 — Concurrency question?

FromKnute Johnson <nospam@rabbitbrush.frazmtn.com>
Date2015-01-31 10:34 -0800
SubjectConcurrency question?
Message-ID<maj766$qjf$1@dont-email.me>
So I have a Map<Integer,String> but it could be a List or an Array, 
shouldn't make any difference.  Access to the Map is controlled by a 
ReadWriteLock.  Several threads read values from the Map and one thread 
can change values or write to or remove key/value pairs from the Map. 
The thread that writes new values to the Map is the EDT, in a 
DocumentListener.  One of the reading threads is time consuming and if 
that thread has the read lock the EDT blocks until it can obtain the 
write lock.  That can generate noticeable delays in data entry through 
the GUI.

Since data entry is slow it doesn't matter much if the data entry 
changes are available during the time period that the time consuming 
thread is reading the Map.  However to ensure that I have current data 
at some point any read access of the Map must be controlled by a read lock.

I needed a way to make the time consuming thread not need to hold the 
read lock for the entire time.  My solution was to acquire the read lock 
and create a List of values from the Map and return the read lock, this 
is very quick.  Then I iterate through the List to perform the time 
consuming task.

I know that it is possible that the GUI could change the Map while the 
time consuming thread is running.  That isn't critical as the data would 
be current the next time the time consuming thread ran.  The reference 
to the List goes out of scope when the time consuming thread completes. 
  Any values that were in the List that were no longer in the Map should 
be available for garbage collection.

Do you see any holes in my logic?  Any suggestions?

Thanks,

Knute...

[toc] | [next] | [standalone]


#30969

FromEric Sosman <esosman@comcast-dot-net.invalid>
Date2015-01-31 14:04 -0500
Message-ID<maj8vj$2ae$1@dont-email.me>
In reply to#30966
On 1/31/2015 1:34 PM, Knute Johnson wrote:
> So I have a Map<Integer,String> but it could be a List or an Array,
> shouldn't make any difference.  Access to the Map is controlled by a
> ReadWriteLock.  Several threads read values from the Map and one thread
> can change values or write to or remove key/value pairs from the Map.
> The thread that writes new values to the Map is the EDT, in a
> DocumentListener.  One of the reading threads is time consuming and if
> that thread has the read lock the EDT blocks until it can obtain the
> write lock.  That can generate noticeable delays in data entry through
> the GUI.
>
> Since data entry is slow it doesn't matter much if the data entry
> changes are available during the time period that the time consuming
> thread is reading the Map.  However to ensure that I have current data
> at some point any read access of the Map must be controlled by a read lock.
>
> I needed a way to make the time consuming thread not need to hold the
> read lock for the entire time.  My solution was to acquire the read lock
> and create a List of values from the Map and return the read lock, this
> is very quick.  Then I iterate through the List to perform the time
> consuming task.
>
> I know that it is possible that the GUI could change the Map while the
> time consuming thread is running.  That isn't critical as the data would
> be current the next time the time consuming thread ran.  The reference
> to the List goes out of scope when the time consuming thread completes.
>   Any values that were in the List that were no longer in the Map should
> be available for garbage collection.
>
> Do you see any holes in my logic?  Any suggestions?

     Sounds reasonable, on the assumption that out-of-date mappings won't
mess up your time-consuming operation.

     Another possibility would be to buffer on the producer side instead.
Rather than updating the Map directly, the EDT could put the updates on
a queue (quickly) and go about its business.  Another thread would wait
for updates to appear on the queue, wait for and grab the write lock,
and then perform the updates.  (This is a bit like the write buffers
found in modern CPU's: They don't wait for memory and cache to be
ready, but just stuff the write into a buffer and trust that it will
eventually get flushed to the hard-to-reach backing store.)

-- 
esosman@comcast-dot-net.invalid
"Don't be afraid of work. Make work afraid of you." -- TLM

[toc] | [prev] | [next] | [standalone]


#30971

FromKnute Johnson <nospam@rabbitbrush.frazmtn.com>
Date2015-01-31 11:23 -0800
Message-ID<maja25$637$1@dont-email.me>
In reply to#30969
On 1/31/2015 11:04, Eric Sosman wrote:
> On 1/31/2015 1:34 PM, Knute Johnson wrote:
>> So I have a Map<Integer,String> but it could be a List or an Array,
>> shouldn't make any difference.  Access to the Map is controlled by a
>> ReadWriteLock.  Several threads read values from the Map and one thread
>> can change values or write to or remove key/value pairs from the Map.
>> The thread that writes new values to the Map is the EDT, in a
>> DocumentListener.  One of the reading threads is time consuming and if
>> that thread has the read lock the EDT blocks until it can obtain the
>> write lock.  That can generate noticeable delays in data entry through
>> the GUI.
>>
>> Since data entry is slow it doesn't matter much if the data entry
>> changes are available during the time period that the time consuming
>> thread is reading the Map.  However to ensure that I have current data
>> at some point any read access of the Map must be controlled by a read
>> lock.
>>
>> I needed a way to make the time consuming thread not need to hold the
>> read lock for the entire time.  My solution was to acquire the read lock
>> and create a List of values from the Map and return the read lock, this
>> is very quick.  Then I iterate through the List to perform the time
>> consuming task.
>>
>> I know that it is possible that the GUI could change the Map while the
>> time consuming thread is running.  That isn't critical as the data would
>> be current the next time the time consuming thread ran.  The reference
>> to the List goes out of scope when the time consuming thread completes.
>>   Any values that were in the List that were no longer in the Map should
>> be available for garbage collection.
>>
>> Do you see any holes in my logic?  Any suggestions?
>
>      Sounds reasonable, on the assumption that out-of-date mappings won't
> mess up your time-consuming operation.
>
>      Another possibility would be to buffer on the producer side instead.
> Rather than updating the Map directly, the EDT could put the updates on
> a queue (quickly) and go about its business.  Another thread would wait
> for updates to appear on the queue, wait for and grab the write lock,
> and then perform the updates.  (This is a bit like the write buffers
> found in modern CPU's: They don't wait for memory and cache to be
> ready, but just stuff the write into a buffer and trust that it will
> eventually get flushed to the hard-to-reach backing store.)
>

I didn't think of that, I like that!  I'll play around with it.

Thanks!

knute...

[toc] | [prev] | [next] | [standalone]


#30970

FromArne Vajhøj <arne@vajhoej.dk>
Date2015-01-31 14:12 -0500
Message-ID<54cd2937$0$289$14726298@news.sunsite.dk>
In reply to#30966
On 1/31/2015 1:34 PM, Knute Johnson wrote:
> So I have a Map<Integer,String> but it could be a List or an Array,
> shouldn't make any difference.  Access to the Map is controlled by a
> ReadWriteLock.  Several threads read values from the Map and one thread
> can change values or write to or remove key/value pairs from the Map.
> The thread that writes new values to the Map is the EDT, in a
> DocumentListener.  One of the reading threads is time consuming and if
> that thread has the read lock the EDT blocks until it can obtain the
> write lock.  That can generate noticeable delays in data entry through
> the GUI.
>
> Since data entry is slow it doesn't matter much if the data entry
> changes are available during the time period that the time consuming
> thread is reading the Map.  However to ensure that I have current data
> at some point any read access of the Map must be controlled by a read lock.
>
> I needed a way to make the time consuming thread not need to hold the
> read lock for the entire time.  My solution was to acquire the read lock
> and create a List of values from the Map and return the read lock, this
> is very quick.  Then I iterate through the List to perform the time
> consuming task.
>
> I know that it is possible that the GUI could change the Map while the
> time consuming thread is running.  That isn't critical as the data would
> be current the next time the time consuming thread ran.  The reference
> to the List goes out of scope when the time consuming thread completes.
>   Any values that were in the List that were no longer in the Map should
> be available for garbage collection.
>
> Do you see any holes in my logic?  Any suggestions?

If the data structure is small, then having the updater create a clone
and update that could provide adequate performance and a very
simple programming model.

Arne

[toc] | [prev] | [next] | [standalone]


#30972

FromKnute Johnson <nospam@rabbitbrush.frazmtn.com>
Date2015-01-31 11:33 -0800
Message-ID<majaks$96l$1@dont-email.me>
In reply to#30970
On 1/31/2015 11:12, Arne Vajhøj wrote:
> On 1/31/2015 1:34 PM, Knute Johnson wrote:
>> So I have a Map<Integer,String> but it could be a List or an Array,
>> shouldn't make any difference.  Access to the Map is controlled by a
>> ReadWriteLock.  Several threads read values from the Map and one thread
>> can change values or write to or remove key/value pairs from the Map.
>> The thread that writes new values to the Map is the EDT, in a
>> DocumentListener.  One of the reading threads is time consuming and if
>> that thread has the read lock the EDT blocks until it can obtain the
>> write lock.  That can generate noticeable delays in data entry through
>> the GUI.
>>
>> Since data entry is slow it doesn't matter much if the data entry
>> changes are available during the time period that the time consuming
>> thread is reading the Map.  However to ensure that I have current data
>> at some point any read access of the Map must be controlled by a read
>> lock.
>>
>> I needed a way to make the time consuming thread not need to hold the
>> read lock for the entire time.  My solution was to acquire the read lock
>> and create a List of values from the Map and return the read lock, this
>> is very quick.  Then I iterate through the List to perform the time
>> consuming task.
>>
>> I know that it is possible that the GUI could change the Map while the
>> time consuming thread is running.  That isn't critical as the data would
>> be current the next time the time consuming thread ran.  The reference
>> to the List goes out of scope when the time consuming thread completes.
>>   Any values that were in the List that were no longer in the Map should
>> be available for garbage collection.
>>
>> Do you see any holes in my logic?  Any suggestions?
>
> If the data structure is small, then having the updater create a clone
> and update that could provide adequate performance and a very
> simple programming model.
>
> Arne

The records are 34 bytes and there can be no more than 10,000 of them. 
In reality the will be no more than a few hundred records at any given time.

I'll think about that, thanks Arne.

knute...

[toc] | [prev] | [next] | [standalone]


#30973

Fromv_borchert@despammed.com (Volker Borchert)
Date2015-01-31 19:20 +0000
Message-ID<maj9tb$l45$3@Gaia.teknon.de>
In reply to#30966
Knute Johnson wrote:
> So I have a Map<Integer,String> [ ... ]
> 
> Do you see any holes in my logic?  Any suggestions?

java.util.concurrent.ConcurrentHashMap<K,V>

-- 

"I'm a doctor, not a mechanic." Dr Leonard McCoy <mccoy@ncc1701.starfleet.fed>
"I'm a mechanic, not a doctor." Volker Borchert  <v_borchert@despammed.com>

[toc] | [prev] | [next] | [standalone]


#30974

FromEric Sosman <esosman@comcast-dot-net.invalid>
Date2015-01-31 15:42 -0500
Message-ID<majen2$psi$1@dont-email.me>
In reply to#30973
On 1/31/2015 2:20 PM, Volker Borchert wrote:
> Knute Johnson wrote:
>> So I have a Map<Integer,String> [ ... ]
>>
>> Do you see any holes in my logic?  Any suggestions?
>
> java.util.concurrent.ConcurrentHashMap<K,V>

     That's fine if the consistency criterion involves only single
mappings.  But if different mappings within the same Map must "agree"
(in some application-dependent sense), atomicity of individual updates
isn't good enough.

     Only Knute knows for sure ...

-- 
esosman@comcast-dot-net.invalid
"Don't be afraid of work. Make work afraid of you." -- TLM

[toc] | [prev] | [next] | [standalone]


#30976

FromKnute Johnson <eternal@knutejohnson.com>
Date2015-01-31 19:51 -0800
Message-ID<mak7rp$d2e$1@dont-email.me>
In reply to#30974
On 01/31/2015 12:42 PM, Eric Sosman wrote:
> On 1/31/2015 2:20 PM, Volker Borchert wrote:
>> Knute Johnson wrote:
>>> So I have a Map<Integer,String> [ ... ]
>>>
>>> Do you see any holes in my logic?  Any suggestions?
>>
>> java.util.concurrent.ConcurrentHashMap<K,V>
>
>      That's fine if the consistency criterion involves only single
> mappings.  But if different mappings within the same Map must "agree"
> (in some application-dependent sense), atomicity of individual updates
> isn't good enough.
>
>      Only Knute knows for sure ...
>

When I first saw Volker's suggestion I thought, no I can't iterate over 
the map without some other synchronization but I looked into the 
ConcurrentHashMap docs and found;

"Similarly, Iterators, Spliterators and Enumerations return elements 
reflecting the state of the hash table at some point at or since the 
creation of the iterator/enumeration. They do not throw 
ConcurrentModificationException. However, iterators are designed to be 
used by only one thread at a time."

As subtle as his suggestion was, I think he may be on to something.  I'm 
going to think about it some more but Volker may have the simplest solution.

-- 

Knute Johnson

[toc] | [prev] | [next] | [standalone]


#30983

FromEric Sosman <esosman@comcast-dot-net.invalid>
Date2015-02-01 09:24 -0500
Message-ID<malcth$3ko$1@dont-email.me>
In reply to#30976
On 1/31/2015 10:51 PM, Knute Johnson wrote:
> On 01/31/2015 12:42 PM, Eric Sosman wrote:
>> On 1/31/2015 2:20 PM, Volker Borchert wrote:
>>> Knute Johnson wrote:
>>>> So I have a Map<Integer,String> [ ... ]
>>>>
>>>> Do you see any holes in my logic?  Any suggestions?
>>>
>>> java.util.concurrent.ConcurrentHashMap<K,V>
>>
>>      That's fine if the consistency criterion involves only single
>> mappings.  But if different mappings within the same Map must "agree"
>> (in some application-dependent sense), atomicity of individual updates
>> isn't good enough.
>>
>>      Only Knute knows for sure ...
>>
>
> When I first saw Volker's suggestion I thought, no I can't iterate over
> the map without some other synchronization but I looked into the
> ConcurrentHashMap docs and found;
>
> "Similarly, Iterators, Spliterators and Enumerations return elements
> reflecting the state of the hash table at some point at or since the
> creation of the iterator/enumeration. They do not throw
> ConcurrentModificationException. However, iterators are designed to be
> used by only one thread at a time."
>
> As subtle as his suggestion was, I think he may be on to something.  I'm
> going to think about it some more but Volker may have the simplest
> solution.

     Hmmm: I still don't think the table's own consistency guarantees are
necessarily strong enough for every application.  For example, consider
a situation where the map expresses a "symmetric" relation where keys
and values are of the same type, and if A -> B then also B -> A.  It
takes two operations to create the two mappings, and if the updating
thread gets interrupted between the two the fact that the reader sees
a consistent-from-the-table's-viewpoint state may be of small comfort.

     So, again: I think it's up to you to figure out what "consistency"
means for your application.  If ConcurrentHashMap's properties provide
what you need, wonderful!  (And I thank you and Volker for teaching me
that its properties extend further than I'd thought!)  But it's not
hard to imagine circumstances that require stronger guarantees than
CHM provides.  "Only Knute knows for sure ..."

-- 
esosman@comcast-dot-net.invalid
"Don't be afraid of work. Make work afraid of you." -- TLM

[toc] | [prev] | [next] | [standalone]


#30979

FromKevin McMurtrie <mcmurtrie@pixelmemory.us>
Date2015-01-31 22:59 -0800
Message-ID<mcmurtrie-36F639.22592131012015@news.sonic.net>
In reply to#30966
In article <maj766$qjf$1@dont-email.me>,
 Knute Johnson <nospam@rabbitbrush.frazmtn.com> wrote:

> So I have a Map<Integer,String> but it could be a List or an Array, 
> shouldn't make any difference.  Access to the Map is controlled by a 
> ReadWriteLock.  Several threads read values from the Map and one thread 
> can change values or write to or remove key/value pairs from the Map. 
> The thread that writes new values to the Map is the EDT, in a 
> DocumentListener.  One of the reading threads is time consuming and if 
> that thread has the read lock the EDT blocks until it can obtain the 
> write lock.  That can generate noticeable delays in data entry through 
> the GUI.
> 
> Since data entry is slow it doesn't matter much if the data entry 
> changes are available during the time period that the time consuming 
> thread is reading the Map.  However to ensure that I have current data 
> at some point any read access of the Map must be controlled by a read lock.
> 
> I needed a way to make the time consuming thread not need to hold the 
> read lock for the entire time.  My solution was to acquire the read lock 
> and create a List of values from the Map and return the read lock, this 
> is very quick.  Then I iterate through the List to perform the time 
> consuming task.
> 
> I know that it is possible that the GUI could change the Map while the 
> time consuming thread is running.  That isn't critical as the data would 
> be current the next time the time consuming thread ran.  The reference 
> to the List goes out of scope when the time consuming thread completes. 
>   Any values that were in the List that were no longer in the Map should 
> be available for garbage collection.
> 
> Do you see any holes in my logic?  Any suggestions?
> 
> Thanks,
> 
> Knute...

That's the usual way to do it.  Perform a snapshot then use the snapshot 
at a leisurely pace without worry.

Eric's recommendation of batch updates is an excellent solution for 
large data sets.

I don't recommend ConcurrentHashMap EVER unless you need atomic 
conditional updates.  The implementation is expensive and it's still not 
entirely lock free.  You need a lot of concurrency from a lot CPU cores 
before you'll see it outperform the old Hashtable class.

-- 
I will not see posts from astraweb, theremailer, dizum, or google
because they host Usenet flooders.

[toc] | [prev] | [next] | [standalone]


#30988

FromArne Vajhøj <arne@vajhoej.dk>
Date2015-02-01 12:55 -0500
Message-ID<54ce6897$0$289$14726298@news.sunsite.dk>
In reply to#30979
On 2/1/2015 1:59 AM, Kevin McMurtrie wrote:
> In article <maj766$qjf$1@dont-email.me>,
>   Knute Johnson <nospam@rabbitbrush.frazmtn.com> wrote:
>> So I have a Map<Integer,String> but it could be a List or an Array,
>> shouldn't make any difference.  Access to the Map is controlled by a
>> ReadWriteLock.  Several threads read values from the Map and one thread
>> can change values or write to or remove key/value pairs from the Map.
>> The thread that writes new values to the Map is the EDT, in a
>> DocumentListener.  One of the reading threads is time consuming and if
>> that thread has the read lock the EDT blocks until it can obtain the
>> write lock.  That can generate noticeable delays in data entry through
>> the GUI.
>>
>> Since data entry is slow it doesn't matter much if the data entry
>> changes are available during the time period that the time consuming
>> thread is reading the Map.  However to ensure that I have current data
>> at some point any read access of the Map must be controlled by a read lock.
>>
>> I needed a way to make the time consuming thread not need to hold the
>> read lock for the entire time.  My solution was to acquire the read lock
>> and create a List of values from the Map and return the read lock, this
>> is very quick.  Then I iterate through the List to perform the time
>> consuming task.
>>
>> I know that it is possible that the GUI could change the Map while the
>> time consuming thread is running.  That isn't critical as the data would
>> be current the next time the time consuming thread ran.  The reference
>> to the List goes out of scope when the time consuming thread completes.
>>    Any values that were in the List that were no longer in the Map should
>> be available for garbage collection.
>
> That's the usual way to do it.  Perform a snapshot then use the snapshot
> at a leisurely pace without worry.
>
> Eric's recommendation of batch updates is an excellent solution for
> large data sets.
>
> I don't recommend ConcurrentHashMap EVER unless you need atomic
> conditional updates.  The implementation is expensive and it's still not
> entirely lock free.  You need a lot of concurrency from a lot CPU cores
> before you'll see it outperform the old Hashtable class.

That is not my experience. CHM seems to be as fast or faster than Ht
in most cases I have seen.

Arne

[toc] | [prev] | [next] | [standalone]


#30989

FromSilvio <silvio@internet.com>
Date2015-02-01 22:19 +0100
Message-ID<54ce987e$0$2956$e4fe514c@news2.news.xs4all.nl>
In reply to#30988
On 02/01/2015 06:55 PM, Arne Vajhøj wrote:
> On 2/1/2015 1:59 AM, Kevin McMurtrie wrote:
>> In article <maj766$qjf$1@dont-email.me>,
>>   Knute Johnson <nospam@rabbitbrush.frazmtn.com> wrote:
>>> So I have a Map<Integer,String> but it could be a List or an Array,
>>> shouldn't make any difference.  Access to the Map is controlled by a
>>> ReadWriteLock.  Several threads read values from the Map and one thread
>>> can change values or write to or remove key/value pairs from the Map.
>>> The thread that writes new values to the Map is the EDT, in a
>>> DocumentListener.  One of the reading threads is time consuming and if
>>> that thread has the read lock the EDT blocks until it can obtain the
>>> write lock.  That can generate noticeable delays in data entry through
>>> the GUI.
>>>
>>> Since data entry is slow it doesn't matter much if the data entry
>>> changes are available during the time period that the time consuming
>>> thread is reading the Map.  However to ensure that I have current data
>>> at some point any read access of the Map must be controlled by a read
>>> lock.
>>>
>>> I needed a way to make the time consuming thread not need to hold the
>>> read lock for the entire time.  My solution was to acquire the read lock
>>> and create a List of values from the Map and return the read lock, this
>>> is very quick.  Then I iterate through the List to perform the time
>>> consuming task.
>>>
>>> I know that it is possible that the GUI could change the Map while the
>>> time consuming thread is running.  That isn't critical as the data would
>>> be current the next time the time consuming thread ran.  The reference
>>> to the List goes out of scope when the time consuming thread completes.
>>>    Any values that were in the List that were no longer in the Map
>>> should
>>> be available for garbage collection.
>>
>> That's the usual way to do it.  Perform a snapshot then use the snapshot
>> at a leisurely pace without worry.
>>
>> Eric's recommendation of batch updates is an excellent solution for
>> large data sets.
>>
>> I don't recommend ConcurrentHashMap EVER unless you need atomic
>> conditional updates.  The implementation is expensive and it's still not
>> entirely lock free.  You need a lot of concurrency from a lot CPU cores
>> before you'll see it outperform the old Hashtable class.
>
> That is not my experience. CHM seems to be as fast or faster than Ht
> in most cases I have seen.
>
> Arne
>
>

Same here.

[toc] | [prev] | [next] | [standalone]


#31065

FromKevin McMurtrie <mcmurtrie@pixelmemory.us>
Date2015-02-06 22:29 -0800
Message-ID<mcmurtrie-22B49E.22295006022015@news.sonic.net>
In reply to#30988
In article <54ce6897$0$289$14726298@news.sunsite.dk>,
 Arne Vajhøj <arne@vajhoej.dk> wrote:

> On 2/1/2015 1:59 AM, Kevin McMurtrie wrote:
> > In article <maj766$qjf$1@dont-email.me>,
> >   Knute Johnson <nospam@rabbitbrush.frazmtn.com> wrote:
> >> So I have a Map<Integer,String> but it could be a List or an Array,
> >> shouldn't make any difference.  Access to the Map is controlled by a
> >> ReadWriteLock.  Several threads read values from the Map and one thread
> >> can change values or write to or remove key/value pairs from the Map.
> >> The thread that writes new values to the Map is the EDT, in a
> >> DocumentListener.  One of the reading threads is time consuming and if
> >> that thread has the read lock the EDT blocks until it can obtain the
> >> write lock.  That can generate noticeable delays in data entry through
> >> the GUI.
> >>
> >> Since data entry is slow it doesn't matter much if the data entry
> >> changes are available during the time period that the time consuming
> >> thread is reading the Map.  However to ensure that I have current data
> >> at some point any read access of the Map must be controlled by a read lock.
> >>
> >> I needed a way to make the time consuming thread not need to hold the
> >> read lock for the entire time.  My solution was to acquire the read lock
> >> and create a List of values from the Map and return the read lock, this
> >> is very quick.  Then I iterate through the List to perform the time
> >> consuming task.
> >>
> >> I know that it is possible that the GUI could change the Map while the
> >> time consuming thread is running.  That isn't critical as the data would
> >> be current the next time the time consuming thread ran.  The reference
> >> to the List goes out of scope when the time consuming thread completes.
> >>    Any values that were in the List that were no longer in the Map should
> >> be available for garbage collection.
> >
> > That's the usual way to do it.  Perform a snapshot then use the snapshot
> > at a leisurely pace without worry.
> >
> > Eric's recommendation of batch updates is an excellent solution for
> > large data sets.
> >
> > I don't recommend ConcurrentHashMap EVER unless you need atomic
> > conditional updates.  The implementation is expensive and it's still not
> > entirely lock free.  You need a lot of concurrency from a lot CPU cores
> > before you'll see it outperform the old Hashtable class.
> 
> That is not my experience. CHM seems to be as fast or faster than Ht
> in most cases I have seen.
> 
> Arne

size(), isEmpty(), and toArray() are slower and must allocate temporary 
objects.  get() and put() can be comparable in speed to HashMap, minus 
some overhead for the internal sharding used to reduce lock scope.

-- 
I will not see posts from astraweb, theremailer, dizum, or google
because they host Usenet flooders.

[toc] | [prev] | [next] | [standalone]


#31072

FromKnute Johnson <eternal@knutejohnson.com>
Date2015-02-07 10:14 -0800
Message-ID<mb5klm$6hu$1@dont-email.me>
In reply to#31065
I want to thank everybody that took time out to answer and discuss my 
questions.  I really appreciate the input.

I've decided to go with the ConcurrentHashMap (thank you again Volker). 
  It reduces the complexity of my code and appears to be plenty fast 
with my small dataset and human speed data entry.  As it turns out my 
code was pretty much duplicating the CHM anyway.

I really like Eric's idea of buffering the producer side with a queue. 
I don't need that here (because of the advantages provided by the CHM) 
but it is an elegant solution for the problem and I will keep that idea 
in my arsenal for the future.

Thanks very much,

-- 

Knute Johnson

[toc] | [prev] | [next] | [standalone]


#31087

FromRobert Klemme <shortcutter@googlemail.com>
Date2015-02-08 19:33 +0100
Message-ID<cjpofjFr4k3U1@mid.individual.net>
In reply to#31065
On 07.02.2015 07:29, Kevin McMurtrie wrote:
> In article <54ce6897$0$289$14726298@news.sunsite.dk>,
>   Arne Vajhøj <arne@vajhoej.dk> wrote:
>
>> On 2/1/2015 1:59 AM, Kevin McMurtrie wrote:

>>> I don't recommend ConcurrentHashMap EVER unless you need atomic
>>> conditional updates.  The implementation is expensive and it's still not
>>> entirely lock free.  You need a lot of concurrency from a lot CPU cores
>>> before you'll see it outperform the old Hashtable class.
>>
>> That is not my experience. CHM seems to be as fast or faster than Ht
>> in most cases I have seen.

> size(), isEmpty(), and toArray() are slower and must allocate temporary
> objects.  get() and put() can be comparable in speed to HashMap, minus
> some overhead for the internal sharding used to reduce lock scope.

But then it is entirely dependent on the use case whether one or the 
other is faster (well, no surprises here).  That is quite a different 
statement than the one you made above which gave the impression that CHM 
is only better in some arcane special cases with "a lot of concurrency".

Kind regards

	robert

-- 
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

[toc] | [prev] | [next] | [standalone]


#31067

Fromolupot douglas <olupotd3@gmail.com>
Date2015-02-07 01:06 -0800
Message-ID<881e1c33-f253-4d72-8c63-617071f5ec0a@googlegroups.com>
In reply to#30966
Hello there, If I may ask, This data your capturing, does it allow for duplicates coz if it does, then a list is alot better but if not, I'd suggest you use a Set instead of a Map and initialize it to a HashSet. Sorry but I don't fully understand your inquiry!

[toc] | [prev] | [next] | [standalone]


#31134

FromHaddock <ffm2002@web.de>
Date2015-02-16 06:32 -0800
Message-ID<9ef5440d-4742-477d-8f61-af89a9091737@googlegroups.com>
In reply to#30966
Just some idea I had when reading the thread... Let's say the writer on every change increments a change counter. 

* Now the long running reader does a part of its work and the returns the read lock. This gives the writer a change to do its work in case it was waiting to obtain the write lock. When the writer is done with its work it increments the change counter. 

* Now the long running reader continues with its work from where it left it when it handed back the read lock voluntarily. It now first checks whether the change counter has changed since the last time. If not, it can continue with its work. Otherwise it might have to start again from the beginning. Depending on how often writes occur, the long running reader might not that often have to throw again the data it already had fetched and there is thus a good trade off in this way.

I don't know exactly the problem case you have, but some idea would be to let the writer add all keys, of which the values were changed, to some change list. When the long running reader re-obtains the read lock after yielding to the writer sees that the change counter has changed it first considers the change list. Eventually, it has not much work to re-do as the keys in the change list mostly point to keys that were not already visited.

Again, just some idea that struck my mind. It may be off, but maybe not ;-).

Cheers, Haddock

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.java.programmer


csiph-web