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


Groups > comp.lang.java.help > #2402 > unrolled thread

Safety Of Non-Synchronized Collections

Started bySteve <tinker123@gmail.com>
First post2013-01-01 15:46 -0500
Last post2013-01-11 08:25 -0500
Articles 11 on this page of 31 — 8 participants

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


Contents

  Safety Of Non-Synchronized Collections Steve <tinker123@gmail.com> - 2013-01-01 15:46 -0500
    Re: Safety Of Non-Synchronized Collections Knute Johnson <nospam@knutejohnson.com> - 2013-01-01 14:18 -0800
      Re: Safety Of Non-Synchronized Collections Lew <lewbloch@gmail.com> - 2013-01-01 15:43 -0800
    Re: Safety Of Non-Synchronized Collections markspace <markspace@nospam.nospam> - 2013-01-01 16:17 -0800
      Re: Safety Of Non-Synchronized Collections Lew <lewbloch@gmail.com> - 2013-01-02 11:12 -0800
        Re: Safety Of Non-Synchronized Collections markspace <markspace@nospam.nospam> - 2013-01-02 12:56 -0800
          Re: Safety Of Non-Synchronized Collections Lew <lewbloch@gmail.com> - 2013-01-02 17:46 -0800
    Re: Safety Of Non-Synchronized Collections Roedy Green <see_website@mindprod.com.invalid> - 2013-01-03 05:59 -0800
      Re: Safety Of Non-Synchronized Collections Lew <lewbloch@gmail.com> - 2013-01-03 15:30 -0800
        Re: Safety Of Non-Synchronized Collections Roedy Green <see_website@mindprod.com.invalid> - 2013-01-09 12:17 -0800
          Re: Safety Of Non-Synchronized Collections Lew <lewbloch@gmail.com> - 2013-01-09 12:56 -0800
            Re: Safety Of Non-Synchronized Collections Daniel Pitts <newsgroup.nospam@virtualinfinity.net> - 2013-01-09 13:10 -0800
              Re: Safety Of Non-Synchronized Collections Lew <lewbloch@gmail.com> - 2013-01-09 14:51 -0800
                Re: Safety Of Non-Synchronized Collections Daniel Pitts <newsgroup.nospam@virtualinfinity.net> - 2013-01-09 15:22 -0800
                  Re: Safety Of Non-Synchronized Collections Lew <lewbloch@gmail.com> - 2013-01-09 16:26 -0800
                    Re: Safety Of Non-Synchronized Collections Daniel Pitts <newsgroup.nospam@virtualinfinity.net> - 2013-01-09 16:42 -0800
                      Re: Safety Of Non-Synchronized Collections Lew <lewbloch@gmail.com> - 2013-01-09 16:54 -0800
                        Re: Safety Of Non-Synchronized Collections Daniel Pitts <newsgroup.nospam@virtualinfinity.net> - 2013-01-10 10:30 -0800
                          Re: Safety Of Non-Synchronized Collections Lew <lewbloch@gmail.com> - 2013-01-10 10:58 -0800
                    Re: Safety Of Non-Synchronized Collections markspace <markspace@nospam.nospam> - 2013-01-09 16:50 -0800
                      Re: Safety Of Non-Synchronized Collections Lew <lewbloch@gmail.com> - 2013-01-09 16:59 -0800
                        Re: Safety Of Non-Synchronized Collections markspace <markspace@nospam.nospam> - 2013-01-10 08:18 -0800
                          Re: Safety Of Non-Synchronized Collections Lew <lewbloch@gmail.com> - 2013-01-10 10:49 -0800
                  Re: Safety Of Non-Synchronized Collections Jukka Lahtinen <jtfjdehf@hotmail.com.invalid> - 2013-01-10 13:37 +0200
                    Re: Safety Of Non-Synchronized Collections Eric Sosman <esosman@comcast-dot-net.invalid> - 2013-01-10 09:27 -0500
                      Re: Safety Of Non-Synchronized Collections Jukka Lahtinen <jtfjdehf@hotmail.com.invalid> - 2013-01-10 17:14 +0200
                        Re: Safety Of Non-Synchronized Collections Eric Sosman <esosman@comcast-dot-net.invalid> - 2013-01-10 11:44 -0500
                          Re: Safety Of Non-Synchronized Collections Jukka Lahtinen <jtfjdehf@hotmail.com.invalid> - 2013-01-10 23:41 +0200
                            Re: Safety Of Non-Synchronized Collections Eric Sosman <esosman@comcast-dot-net.invalid> - 2013-01-10 17:14 -0500
                              Re: Safety Of Non-Synchronized Collections Jukka Lahtinen <jtfjdehf@hotmail.com.invalid> - 2013-01-11 09:10 +0200
                                Re: Safety Of Non-Synchronized Collections Eric Sosman <esosman@comcast-dot-net.invalid> - 2013-01-11 08:25 -0500

Page 2 of 2 — ← Prev page 1 [2]


#2426

FromLew <lewbloch@gmail.com>
Date2013-01-09 16:59 -0800
Message-ID<faf0aa77-0299-48ea-9640-69124203b766@googlegroups.com>
In reply to#2424
markspace wrote:
> Lew wrote:
>> http://rayfd.me/2007/11/11/when-a-synchronized-class-isnt-threadsafe/
> 
>> This is elementary concurrency gotcha lore.
> 
> Note this sentence from the article: "Changing the synchronized List to 
> Vector doesn't help either."

Exactly! MY POINT!
 
> Vector is thread safe.  Objects wrapped by Collections.synchronized() 

'Vector' is *not* thread safe!

That's the point of that article.

> are thread safe.  This does not guarantee that every use of those 
> classes is safe, or correct.
> 
> Their example is of a single collection which is accessed by multiple 
> threads.  As they show their example produces errors.  This is an issue 
> of atomicity, not thread safety.  The single collection is still 

It is an issue with the idea that people confuse synchronized methods with thread safety.

From the Brian Goetz article I quoted upthread:

"Thread-safe
Thread-safe objects have the properties described above in the section "Thread Safety" -- that 
constraints imposed by the class's specification continue to hold when the object is accessed by 
multiple threads, regardless of how the threads are scheduled by the runtime environment, without any 
additional synchronization. This thread-safety guarantee is a strong one -- many classes, like 
Hashtable or Vector, will fail to meet this stringent definition."

> perfectly safe, in spite of the errors.  There are no data races. 

There are synchronization issues because a person coding that way thinks the 
synchronized-method class is thread safe when it isn't.

You, too, are pulling No True Scotsman, and I will still use Brian Goetz's definitions 
over yours.

> However, the program produces errors because it is poorly designed.  It 
> requires atomicity, and synchronized methods don't provide that across 
> multiple method calls.

Because the class *is not thread safe*!

> So the problem is really one of quibbling over terminology.  Thread 

Terminology matters. It's worth "quibbling". (Calling it by something pejorative 
does not diminish its real importance.)

> safety and atomicity both fall under the more general heading of 
> concurrency and concurrent programming.  Thread safety and atomicity are 

A.k.a., threads.

> not the same thing.  They overlap a bit, but not much, so it's best to 

Again, look at the definition and stop changing it.

> actually understand what is being discussed.  In Java, thread safe means 
> an absence of data races, but that's all.  It says nothing about 
> atomicity, or the correctness of any given program.

Your definition is wrong.

-- 
Lew

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


#2430

Frommarkspace <markspace@nospam.nospam>
Date2013-01-10 08:18 -0800
Message-ID<kcmpl4$6jd$2@dont-email.me>
In reply to#2426
On 1/9/2013 4:59 PM, Lew wrote:

>  From the Brian Goetz article I quoted upthread:

I didn't see that article upthread.  Do you mean this one?

<http://www.ibm.com/developerworks/java/library/j-jtp09263/index.html>

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


#2433

FromLew <lewbloch@gmail.com>
Date2013-01-10 10:49 -0800
Message-ID<bc43b7ef-3ef7-4963-805c-29c77d830510@googlegroups.com>
In reply to#2430
markspace wrote:
> Lew wrote:
>>  From the Brian Goetz article I quoted upthread:
> 
> I didn't see that article upthread.  Do you mean this one?
> 
> <http://www.ibm.com/developerworks/java/library/j-jtp09263/index.html>

Aye.

-- 
Lew

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


#2427

FromJukka Lahtinen <jtfjdehf@hotmail.com.invalid>
Date2013-01-10 13:37 +0200
Message-ID<lvd2xdw9p0.fsf@saunalahti.fi>
In reply to#2420
Daniel Pitts <newsgroup.nospam@virtualinfinity.net> writes:
> On 1/9/13 2:51 PM, Lew wrote:

>> 'StringBuffer' is no more thread safe than any other class with
>> synchronized methods.

> Which is more safe than other classes without synchronized methods.
> They are thread-safe to the point that each method call is atomic. What
> else could you ask for? They didn't lie.

Whenever thread safety is needed, you mostly need to synchronize not
only the single method call to an instance of StringBuffer or some other
class of the jdk, but also some context around it.
And when you add a synchronized block around some code containing the
StringBuffer call, the synchronization of the StringBuffer method is
most likely not needed any more, because of your own synchronized
block. And then you can just use StringBuilder.

Of course, there may be situations where the StringBuffer method
is all that needs to be syncrhonized, and that's where StringBuffer
should be used.

-- 
Jukka Lahtinen

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


#2428

FromEric Sosman <esosman@comcast-dot-net.invalid>
Date2013-01-10 09:27 -0500
Message-ID<kcmj4t$vkm$1@dont-email.me>
In reply to#2427
On 1/10/2013 6:37 AM, Jukka Lahtinen wrote:
> Daniel Pitts <newsgroup.nospam@virtualinfinity.net> writes:
>> On 1/9/13 2:51 PM, Lew wrote:
>
>>> 'StringBuffer' is no more thread safe than any other class with
>>> synchronized methods.
>
>> Which is more safe than other classes without synchronized methods.
>> They are thread-safe to the point that each method call is atomic. What
>> else could you ask for? They didn't lie.
>
> Whenever thread safety is needed, you mostly need to synchronize not
> only the single method call to an instance of StringBuffer or some other
> class of the jdk, but also some context around it.
> And when you add a synchronized block around some code containing the
> StringBuffer call, the synchronization of the StringBuffer method is
> most likely not needed any more, because of your own synchronized
> block. And then you can just use StringBuilder.

     This is probably not the case, because another thread might
call an (unsynchronized) StringBuilder method while you're in
the middle of your synchronized block:

	StringBuilder sb = ...;

	// Thread T1:
	synchronized(sb) {
	    if (sb.charAt(sb.length() - 1) == '\n') {
	        sb.deleteCharAt(sb.length() - 1);
	    }
	}

	// Thread T2:
	sb.append("Gotcha!");

The synchronization in T1's code is no protection against
interference from T2.  If `sb' were changed from a StringBuilder
to a StringBuffer, the race condition would disappear.

-- 
Eric Sosman
esosman@comcast-dot-net.invalid

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


#2429

FromJukka Lahtinen <jtfjdehf@hotmail.com.invalid>
Date2013-01-10 17:14 +0200
Message-ID<lvbocxdq9t.fsf@saunalahti.fi>
In reply to#2428
Eric Sosman <esosman@comcast-dot-net.invalid> writes:
> On 1/10/2013 6:37 AM, Jukka Lahtinen wrote:
>> Daniel Pitts <newsgroup.nospam@virtualinfinity.net> writes:
>>> On 1/9/13 2:51 PM, Lew wrote:

>>>> 'StringBuffer' is no more thread safe than any other class with
>>>> synchronized methods.

>>> Which is more safe than other classes without synchronized methods.
>>> They are thread-safe to the point that each method call is atomic. What
>>> else could you ask for? They didn't lie.

>> Whenever thread safety is needed, you mostly need to synchronize not
>> only the single method call to an instance of StringBuffer or some other
>> class of the jdk, but also some context around it.

>     This is probably not the case, because another thread might
> call an (unsynchronized) StringBuilder method while you're in
> the middle of your synchronized block:

If you use the same instance in many places, potentially in different
threads, you should of course synchronize all of them using the same
lock.

> 	StringBuilder sb = ...;
> 	// Thread T1:
> 	synchronized(sb) {
> 	    if (sb.charAt(sb.length() - 1) == '\n') {
> 	        sb.deleteCharAt(sb.length() - 1);
> 	    }
> 	}

This is an example of what I wrote above. You need that synchronization
to prevent others from modifying sb between the charAt, length and
deletCharAt calls anyway.
Using StringBuffer instead of StringBuilder does NOT accomplish that.

> 	// Thread T2:
> 	sb.append("Gotcha!");

And so, this should be

synchronized(sb) {
    sb.append("Gotcha?");
}

> The synchronization in T1's code is no protection against
> interference from T2.  If `sb' were changed from a StringBuilder
> to a StringBuffer, the race condition would disappear.

Neither is using StringBuffer.
Like I said, you could be in trouble if T2 makes that call somewhere
between the calls to the first sb.length() and sb.deletCharAt in T1 even
if sb is a StringBuffer.

-- 
Jukka Lahtinen

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


#2431

FromEric Sosman <esosman@comcast-dot-net.invalid>
Date2013-01-10 11:44 -0500
Message-ID<kcmr59$hp6$1@dont-email.me>
In reply to#2429
On 1/10/2013 10:14 AM, Jukka Lahtinen wrote:
> Eric Sosman <esosman@comcast-dot-net.invalid> writes:
>> On 1/10/2013 6:37 AM, Jukka Lahtinen wrote:
>>> Daniel Pitts <newsgroup.nospam@virtualinfinity.net> writes:
>>>> On 1/9/13 2:51 PM, Lew wrote:
>
>>>>> 'StringBuffer' is no more thread safe than any other class with
>>>>> synchronized methods.
>
>>>> Which is more safe than other classes without synchronized methods.
>>>> They are thread-safe to the point that each method call is atomic. What
>>>> else could you ask for? They didn't lie.
>
>>> Whenever thread safety is needed, you mostly need to synchronize not
>>> only the single method call to an instance of StringBuffer or some other
>>> class of the jdk, but also some context around it.
>
>>      This is probably not the case, because another thread might
>> call an (unsynchronized) StringBuilder method while you're in
>> the middle of your synchronized block:
>
> If you use the same instance in many places, potentially in different
> threads, you should of course synchronize all of them using the same
> lock.
>
>> 	StringBuilder sb = ...;
>> 	// Thread T1:
>> 	synchronized(sb) {
>> 	    if (sb.charAt(sb.length() - 1) == '\n') {
>> 	        sb.deleteCharAt(sb.length() - 1);
>> 	    }
>> 	}
>
> This is an example of what I wrote above. You need that synchronization
> to prevent others from modifying sb between the charAt, length and
> deletCharAt calls anyway.
> Using StringBuffer instead of StringBuilder does NOT accomplish that.
>
>> 	// Thread T2:
>> 	sb.append("Gotcha!");
>
> And so, this should be
>
> synchronized(sb) {
>      sb.append("Gotcha?");
> }
>
>> The synchronization in T1's code is no protection against
>> interference from T2.  If `sb' were changed from a StringBuilder
>> to a StringBuffer, the race condition would disappear.
>
> Neither is using StringBuffer.
> Like I said, you could be in trouble if T2 makes that call somewhere
> between the calls to the first sb.length() and sb.deletCharAt in T1 even
> if sb is a StringBuffer.

     If T2 makes such a call while T1 is in the synchronized block,
T2 will stall until T1's synchronized block finishes (or perhaps
longer).  No race, no trouble.

-- 
Eric Sosman
esosman@comcast-dot-net.invalid

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


#2435

FromJukka Lahtinen <jtfjdehf@hotmail.com.invalid>
Date2013-01-10 23:41 +0200
Message-ID<lvr4lspvge.fsf@saunalahti.fi>
In reply to#2431
Eric Sosman <esosman@comcast-dot-net.invalid> writes:
> On 1/10/2013 10:14 AM, Jukka Lahtinen wrote:
>> Eric Sosman <esosman@comcast-dot-net.invalid> writes:
>>> On 1/10/2013 6:37 AM, Jukka Lahtinen wrote:

>>>> Whenever thread safety is needed, you mostly need to synchronize not
>>>> only the single method call to an instance of StringBuffer or some other
>>>> class of the jdk, but also some context around it.

>>>      This is probably not the case, because another thread might
>>> call an (unsynchronized) StringBuilder method while you're in
>>> the middle of your synchronized block:

>> If you use the same instance in many places, potentially in different
>> threads, you should of course synchronize all of them using the same
>> lock.

>>> 	StringBuilder sb = ...;
>>> 	// Thread T1:
>>> 	synchronized(sb) {
>>> 	    if (sb.charAt(sb.length() - 1) == '\n') {
>>> 	        sb.deleteCharAt(sb.length() - 1);
>>> 	    }
>>> 	}

>>> 	// Thread T2:
>>> 	sb.append("Gotcha!");

>> And so, this should be
>> synchronized(sb) {
>>      sb.append("Gotcha?");
>> }

>>> The synchronization in T1's code is no protection against
>>> interference from T2.  If `sb' were changed from a StringBuilder
>>> to a StringBuffer, the race condition would disappear.

>> Like I said, you could be in trouble if T2 makes that call somewhere
>> between the calls to the first sb.length() and sb.deletCharAt in T1 even
>> if sb is a StringBuffer.

>     If T2 makes such a call while T1 is in the synchronized block,
> T2 will stall until T1's synchronized block finishes (or perhaps
> longer).  No race, no trouble.

Only if you add the synchronization also to T2, like I did
above. Without that, nothing will prevent T2 from calling sb.append
between the separate calls from T1 to sb, no matter whether sb is
StringBuffer or StringBuilder.

-- 
Jukka Lahtinen

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


#2436

FromEric Sosman <esosman@comcast-dot-net.invalid>
Date2013-01-10 17:14 -0500
Message-ID<kcneh0$kmh$1@dont-email.me>
In reply to#2435
On 1/10/2013 4:41 PM, Jukka Lahtinen wrote:
> Eric Sosman <esosman@comcast-dot-net.invalid> writes:
>> On 1/10/2013 10:14 AM, Jukka Lahtinen wrote:
>>> Eric Sosman <esosman@comcast-dot-net.invalid> writes:
>>>> On 1/10/2013 6:37 AM, Jukka Lahtinen wrote:
>
>>>>> Whenever thread safety is needed, you mostly need to synchronize not
>>>>> only the single method call to an instance of StringBuffer or some other
>>>>> class of the jdk, but also some context around it.
>
>>>>       This is probably not the case, because another thread might
>>>> call an (unsynchronized) StringBuilder method while you're in
>>>> the middle of your synchronized block:
>
>>> If you use the same instance in many places, potentially in different
>>> threads, you should of course synchronize all of them using the same
>>> lock.
>
>>>> 	StringBuilder sb = ...;
>>>> 	// Thread T1:
>>>> 	synchronized(sb) {
>>>> 	    if (sb.charAt(sb.length() - 1) == '\n') {
>>>> 	        sb.deleteCharAt(sb.length() - 1);
>>>> 	    }
>>>> 	}
>
>>>> 	// Thread T2:
>>>> 	sb.append("Gotcha!");
>
>>> And so, this should be
>>> synchronized(sb) {
>>>       sb.append("Gotcha?");
>>> }
>
>>>> The synchronization in T1's code is no protection against
>>>> interference from T2.  If `sb' were changed from a StringBuilder
>>>> to a StringBuffer, the race condition would disappear.
>
>>> Like I said, you could be in trouble if T2 makes that call somewhere
>>> between the calls to the first sb.length() and sb.deletCharAt in T1 even
>>> if sb is a StringBuffer.
>
>>      If T2 makes such a call while T1 is in the synchronized block,
>> T2 will stall until T1's synchronized block finishes (or perhaps
>> longer).  No race, no trouble.
>
> Only if you add the synchronization also to T2, like I did
> above. Without that, nothing will prevent T2 from calling sb.append
> between the separate calls from T1 to sb, no matter whether sb is
> StringBuffer or StringBuilder.

     Quoth the Javadoc for StringBuffer:

	"Whenever an operation occurs involving a source sequence
	(such as appending or inserting from a source sequence)
	this class synchronizes only on the string buffer performing
	the operation [...]"

Therefore, StringBuffer's append() method synchronizes on the
StringBuffer instance being appended to, using the instance's
own monitor.  That's the same monitor used by the explicit
`synchronized' in my code example (modified to use StringBuffer
instead of StringBuilder), so there is a mutual exclusion between
the body of append() and the body of the `synchronized' block.
The two executions cannot overlap, interfere, intertwine, entangle,
or cohabit.

     (Oddly enough, although StringBuffer's Javadoc says "the
methods are synchronized," only for source-destination methods
does it actually specify what object's lock is used -- and even
that comes as a by-product of saying what object's lock *isn't*
used.  Had my example used setCharAt(), say, there could have
been a quibble about whether a mutual exclusion actually exists --
but with append() there's no question.)

-- 
Eric Sosman
esosman@comcast-dot-net.invalid

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


#2437

FromJukka Lahtinen <jtfjdehf@hotmail.com.invalid>
Date2013-01-11 09:10 +0200
Message-ID<lvzk0gnqjy.fsf@saunalahti.fi>
In reply to#2436
Eric Sosman <esosman@comcast-dot-net.invalid> writes:
> On 1/10/2013 4:41 PM, Jukka Lahtinen wrote:
>> Eric Sosman <esosman@comcast-dot-net.invalid> writes:

>>>      If T2 makes such a call while T1 is in the synchronized block,
>>> T2 will stall until T1's synchronized block finishes (or perhaps
>>> longer).  No race, no trouble.

>> Only if you add the synchronization also to T2, like I did

>     Quoth the Javadoc for StringBuffer:
> 	"Whenever an operation occurs involving a source sequence
> 	(such as appending or inserting from a source sequence)
> 	this class synchronizes only on the string buffer performing
> 	the operation [...]"

Oh, I stand corrected. It works in this case.

But still I claim that when synchronization is needed, it is MOSTLY
needed for a block broader than just the single call to a method of a
jdk class instance.
(And before anybody calls for "true Scotsman", I remembered to include
the word mostly in my original claim as well.)

-- 
Jukka Lahtinen

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


#2438

FromEric Sosman <esosman@comcast-dot-net.invalid>
Date2013-01-11 08:25 -0500
Message-ID<kcp3t8$pg4$1@dont-email.me>
In reply to#2437
On 1/11/2013 2:10 AM, Jukka Lahtinen wrote:
> [...]
> But still I claim that when synchronization is needed, it is MOSTLY
> needed for a block broader than just the single call to a method of a
> jdk class instance.

     Yes, often.  Somebody elsethread made a distinction between
"operations" and "method calls" (I'm paraphrasing, because I can't
find the post at the moment).  If all the necessary methods are
synchronized, they are individually thread-safe -- but if an
"operation" uses multiple method calls, the "operation" might
not be.

     This principle even applies to atomics, which synchronize
without `synchronized'.  With an AtomicInteger named `atom',
this is thread-safe:

	atom.addAndGet(3);

... but this is not:

	// Make sure the value is even:
	atom.addAndGet(atom.get() & 1);

Each of `get' and `addAndGet' is individually thread-safe, but
the "operation" composed of both is not.

-- 
Eric Sosman
esosman@comcast-dot-net.invalid

[toc] | [prev] | [standalone]


Page 2 of 2 — ← Prev page 1 [2]

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


csiph-web