|
Larry, As always sometimes you have to compromise your standards. With Swing, you are dealing with an entirely different thing than Servlets. Performance is a much bigger concern in a Servlet because the work is all done on the server and there is a lot more contention. I think I made the assumption that Daniel is talking about Servlets, where it makes sense to avoid synchronization and not Swing. I am very familiar with the performance gains I have achieved in servlets by avoiding synchronization. One example of the base objects you talk about is a HashMaps. Removing synchronized read-only access and writing to a non-synchronized clone of the HashMap can make a measurable difference. As you say in a pure OO model you would avoid parameterizing your instance variables, cloning, etc. In our case we have to deliver applications on our current hardware. David Morris >>> lwloen@us.ibm.com 04/17/02 09:23AM >>> >Daniel, >The types of errors you will experience are difficult >to track down, that is why they associate this with the >plague. I generally pass those values through as >parameters and avoid synchronization. You >have to synchronize the whole block from setter to >return from any method that uses those variable and >expects to find your set values. >David Morris This is great for procedural programming, but not for real O-O. If you must mix threads and objects, then there is no real alternative to mastering the "synchronized" keyword and when to use it (most of the time). After all, half the point of objects is to hold critical state. Many (but by no means all) of the ordinary base objects are already thread safe in that they synchronize everything in sight. StringBuffer is one notable example. As will be seen in a second, String manages this another way. Basically, when you get to threads, there are three cases: 1. A given object will be "guaranteed" to be accessed by only one thread. If the guarantee slips, bugs result. I don't use it much, but I think the whole Swing complex meets this model. In this model, no synchronization needed or wanted. This is where the nasty bugs live when the guarantee slips up. 2. A given object will be referenced, even if only occassionally, by more than one thread. If you even suspect this is going to happen, then sychronization is required for everything except constructors. In some cases, even static (class) methods will need some amount of synchronization. A few more difficult cases will require the synchronized keyword on a few blocks of code, but most will work fine with the keyword applied to the method itself, which implies the lock is held for the duration of the method. Bugs result here mainly from forgetting to add the keyword, especially in the "block" case. At the method level, an eyeball inspection pretty much puts bugs to rest beforehand. 3. An object is "immutable." This is not a declared, fixed property, but one which (if coded carefully and correctly) is noted and even exploited by the underlying JVM. It is an object that is modified only when constructed and thereafter never changed. Since object construction is inherently single threaded (at least, any sensible constructor is), the "immutable" object can be treated as ever-after thread safe as it is "read only". This is because, post-construction, it is never modified and so needs no synchronization. String is probably the most famous such object. If you code: String a = "This " + "that"; or even String b = a + " and another"; or even still: a = b + a + " yet another"; . . .then variable a is "thread safe" (because it is an ordinary stack variable) and (tricky here) the underlying String objects are thread safe because each "+" operation constructs a new one. If someone still points, somehow, to the older value of "a" above, that object is still good and the fact that variable "a" now points to a different String doesn't matter a bit. In fact, this closely corresponds to people's intuition, perhaps even better seen in the following: BigInteger c = new BigInteger("1"); repository.recordCSomewhereInHere(c); c = c.add(new BigInteger("2")); // c = c + 2 . . .where "c" is now pointing to a BigInteger with a value of 3 and yet the original value of 1 is some other BigInteger object in whatever "repository" does to store what's passed to it. This is all workable because BigInteger is also "immutable." One potentially interesting and dangerous fact about Java is that the synchronized keyword is not part of the signature. So, an inherited method could be synchronized and the parent method not and vice-versa. Or, so it was around 1.1.6 last time I checked that out. Java originally wanted everyone to do 2 and 3 (especially 3). This was no secret at the time, though it may not be extensively written up in pubs. If you use those rules, individually or collectively, then thread safety is easy to manage, even if you very belatedly decide to subject your object to a thread-rich environment. However, practicality seems to have reared its ugly head and 1 is now seen fairly extensively. The place I noticed this first coming into play was when Swing was added. Larry W. Loen - Senior Linux, Java, and iSeries Performance Analyst Dept HP4, Rochester MN
As an Amazon Associate we earn from qualifying purchases.
This mailing list archive is Copyright 1997-2024 by midrange.com and David Gibbs as a compilation work. Use of the archive is restricted to research of a business or technical nature. Any other uses are prohibited. Full details are available on our policy page. If you have questions about this, please contact [javascript protected email address].
Operating expenses for this site are earned using the Amazon Associate program and Google Adsense.