"Il y a peu de choses qui me soient impossibles..."
No more Blub for me, thank you, Vicar.
chris webster wrote:More generally, immutable objects have certain advantages e.g. immutable objects are thread-safe. If you and I have references to the same object A in separate threads, we still can't change the contents of A, so we know that we will always get the same contents when we read A in our separate threads. If A was mutable, your thread might change it so my view of A was no longer consistent with yours.
"Il y a peu de choses qui me soient impossibles..."
Stevens Miller wrote:Chris, may I probe that point a bit? I'm doing a lot of multi-threaded coding lately, and can use all the guidance I can get.
Stevens Miller wrote:...Is that a valid way to look at this aspect of immutability? That it prevents code from changing an object's contents, whereas, for mutable objects, we can only trust each other not to make changes?
"Immutable classes are easier to design, implement, and use than mutable classes. They are less prone to error and are more secure."
Classes should be immutable unless there's a very good reason to make them mutable. Immutable classes provide many advantages, and their only disadvantage is the potential for performance problems under certain circumstances.
...
If a class cannot be made immutable, limit its mutability as much as possible. Reducing the number of states in which an object can exist makes it easier to reason about the object and reduces the likelihood of errors. Therefore, make every field final unless there is a compelling reason to make it nonfinal.
No more Blub for me, thank you, Vicar.
Stevens Miller wrote:if you and I have references to the same object A in separate threads, we can agree not to change the contents of A, whether it is immutable or not. If A is immutable, that agreement is enforced by the object's design. If A is not immutable, the agreement will still yield the same benefit as if A were immutable, just without the design of A enforcing the agreement upon us. Put another way, the same code as is allowed when A is immutable would work just as well, and be just as effective in guaranteeing that neither thread changes A, when A is mutable.
Stevens Miller wrote:Seems to me that, if one benefit of immutability is that two threads can rely on the content of an immutable object not to change, then the code in each thread would never try to change that object's contents. For an immutable object like, say, a String, there is no way for your Java code to change its contents. But is that a "benefit" of the immutability of the object, or a restriction imposed upon the program? Or both? What I'm (probably clumsily) trying to get at is that, if you and I have references to the same object A in separate threads, we can agree not to change the contents of A, whether it is immutable or not...
Is that a valid way to look at this aspect of immutability? That it prevents code from changing an object's contents, whereas, for mutable objects, we can only trust each other not to make changes?
"Leadership is nature's way of removing morons from the productive flow" - Dogbert
Articles by Winston can be found here
Mike Simmons wrote:
Stevens Miller wrote:Put another way, the same code as is allowed when A is immutable would work just as well, and be just as effective in guaranteeing that neither thread changes A, when A is mutable.
No, that's not quite true. There are cases where the JVM handles fields a little differently if they are final than if they are not final - and in a multi-threaded context, if you access a nonfinal field without any synchronization, you can get some very unintuitive results. Like a field may show up as 0 or null even though another thread initialized it to some other value.
"Il y a peu de choses qui me soient impossibles..."
Winston GutkowskiMost large projects involve many programmers of differing skills, so it's not just about managing your objects; it's also making sure that someone else (a 'client', but possibly also a colleague) [i wrote:can't[/i] do anything that you didn't intend them to.
"Il y a peu de choses qui me soient impossibles..."
chris webster wrote:The FP brigade seem to require immutability because it means that every time you call a function with the same inputs you get the same output, with no side effects, which is obviously pretty important.
Even in Java, Joshua Bloch's "Effective Java" (Bloch, Joshua. Effective Java (2nd Edition), pp. 73ff) has a section on why it's a good idea to make your classes immutable if possible...
"Il y a peu de choses qui me soient impossibles..."
Stevens Miller wrote:As for FP, well... "What's so good about functional programming?" ...
No more Blub for me, thank you, Vicar.
Stevens Miller wrote:Mike, I think if the other thread can initialize a field, that is going to call for synchronization whether the other field is final or not. That's because the thread that does not initialize the field has no way, without synchronization, of knowing if the other thread has initiatialized that field at any given moment or not. Even if making it final guarantees both threads see the same value after initialization, it doesn't help the non-initializing thread's need to be able to determine if the field has been initialized or not. OTOH, if the object has been initialized before another thread is created, I believe synchronization is implicit and that any caching or other issues that might confuse the second thread are avoided (since it must load the field at least once upon the first reference, and, by that time, it has already been initialized).
Mike Simmons wrote: Or maybe they're under the illusion that just because no one is changing the fields after initialization (which may have even been done in the constructor), they don't need to worry about mutability. But if the field is not final, they're wrong.
"Il y a peu de choses qui me soient impossibles..."
Stevens Miller wrote: I got my degree in 1988. Yes, we had computers in 1988.
)
Bear Bibeault wrote:
Stevens Miller wrote: I got my degree in 1988. Yes, we had computers in 1988.
)
Whippersnapper!
Bear has been turning coffee into quality software since 1976 when he starting programming in BASIC on a Control Data Cyber.
"Il y a peu de choses qui me soient impossibles..."
Stevens Miller wrote:
I think I kept up with all the rest, but this last part I'm not grokking yet. If a field is initialized before the second, accessing thread is created, I believe synchronization is implicit.
Stevens Miller wrote:If the field is initialized after the second (again, accessing) thread is created, it seems that synchronization is necessary, whether it is final or not, because there is no way for the second thread to know if the field has been initialized without synchronization.
Mike Simmons wrote:
Stevens Miller wrote:
I think I kept up with all the rest, but this last part I'm not grokking yet. If a field is initialized before the second, accessing thread is created, I believe synchronization is implicit.
Well, yeah, that would sure make intuitive sense. But it isn't actually the case. The problem is that Java allows for all sorts of compiler optimizations, potentially reordering operations and caching values as long as the reordering and caching would have no effect on behavior as seen from a single-threaded model.
Mike Simmons wrote:
Stevens Miller wrote:If the field is initialized after the second (again, accessing) thread is created, it seems that synchronization is necessary, whether it is final or not, because there is no way for the second thread to know if the field has been initialized without synchronization.
If the field is final, then the second thread will not be allowed to access anything about the object until after the constructor completes. Even if the thread started before the field was initialized. But no such guarantee exists for a non-final field.
"Il y a peu de choses qui me soient impossibles..."
Bear Bibeault wrote:I still miss the clatter those teletypes made. (Not.)
"Il y a peu de choses qui me soient impossibles..."
17.4.5 wrote: A write to a volatile field (8.3.1.4) happens-before every subsequent read of that field.
17.5 wrote:A thread that can only see a reference to an object after that object has been completely initialized is guaranteed to see the correctly initialized values for that object's final fields.
(emphasis mine)
17.4.4 wrote:An action that starts a thread synchronizes-with the first action in the thread it starts.
"Il y a peu de choses qui me soient impossibles..."
Mike Simmons wrote:I think the answer to all those questions is "yes" - except the last "am I overlooking something", which is "no". But that's on a quick read-through, and to be honest I don't remember all the details of how these rules work; it takes some time and effort to reabsorb them. I'll try to give it a longer look later. Glad you're finding the link useful.
"Il y a peu de choses qui me soient impossibles..."
Stevens Miller wrote:Keep the good stuff comin', boys. I may be old, but I ain't dead yet.
"Leadership is nature's way of removing morons from the productive flow" - Dogbert
Articles by Winston can be found here
Hollerith cards. I have made them out of Hollerith cards. (The real fun with paper tape was saving the dots the ASR 33 left in that bucket underneath the punch. Because of the little bit of lubricating oil on that tape, they stuck really well and were very hard to comb out when you threw them in the girls' hair in the hallway.)Winston Gutkowski wrote:
Stevens Miller wrote:Keep the good stuff comin', boys. I may be old, but I ain't dead yet.
Like Bear said: whippersnapper.
Me: First programming at school - Basic on a PDP-8E in 1971. First job (1976): COBOL on an ICL-1906S, running GEORGE III (brilliant OS). 6 months earlier and I'd have been doing Autocoder on a 1401. Anyone else here still remember how to make Christmas stars out of paper tape?
Heh. At least Java is pretty clearly spec'ed about those things. Try reading the MSDN on how you can be sure (or if you even can be sure) that you have achieved shared memory coherence between threads under Windows. It says you can trust the synching functions to erect fences for you, which is great for handling reordering, but it never quite seems to say you can be sure your shared data isn't being cached in another thread (which means you can't be sure it's got the same value in each thread). There's some tantalizing stuff about globals, and so on, that I think makes the promise you need, but... well, I hope my code works, that's all I can say.Just a quickie point to add to Mike's great advice: That re-ordering business is possibly the most important thing to know about with the memory model. It applies to - or rather, is restricted by - final, AND volatile fields (and, of course, synchronization) by imposing 'happens before' rules. Personally, I have to re-read them pretty much every time I'm doing something complex, but I blame it on the Alzheimer's.
"Il y a peu de choses qui me soient impossibles..."
Did you have the paper tape with holes in, and the little hand‑operated reels to wind it up neatly? Did you use ctrl‑shift‑P‑repeat to get the neat blank leaders and tails for the paper tape? I can remember trying to model extraction columns in BASIC back in 1971. Time‑sharing on a Honeywell system.Stevens Miller wrote: . . . (On one of these, no less.) . . .
Campbell Ritchie wrote:
Did you have the paper tape with holes in, and the little hand‑operated reels to wind it up neatly? Did you use ctrl‑shift‑P‑repeat to get the neat blank leaders and tails for the paper tape? I can remember trying to model extraction columns in BASIC back in 1971. Time‑sharing on a Honeywell system.Stevens Miller wrote: . . . (On one of these, no less.) . . .
"Il y a peu de choses qui me soient impossibles..."
Well doneprateek garg wrote:After some r&d . . .
Do the next thing next. That’s a pretty good rule. Read the tiny ad, that’s a pretty good rule, too.
a bit of art, as a gift, that will fit in a stocking
https://gardener-gift.com
|