Jason Voegele

Greenhorn
+ Follow
since Oct 12, 2001
Cows and Likes
Cows
Total received
0
In last 30 days
0
Total given
0
Likes
Total received
0
Received in last 30 days
0
Total given
0
Given in last 30 days
0
Forums and Threads
Scavenger Hunt
expand Ranch Hand Scavenger Hunt
expand Greenhorn Scavenger Hunt

Recent posts by Jason Voegele

Originally posted by Max Habibi:
Jason,
I agree with CL, you don't want to nest synchronized locks, especially on the same object. Try the following,


Well, there's a problem with the above code in that if employees is indeed null, then the code basically reduces to synchronized(null) , which, I'm pretty sure, is undefined behavior.
Thanks for your help, though.
Jason
15 years ago
Thanks to all of you who have provided answers to my query here.
To address the issues brought up surrounding whether or not it is a good idea for my application to release a lock while performing an expensive operation, the answer is that it will not cause any real harm. Peter mentioned that (in my example), certain timing conditions may cause the employee list to be loaded twice. This is not ideal, but it is acceptable, and given the absolutely dreadful connection to the database, I'm willing to allow this to happen in favor of releasing locks during (extremely expensive) database calls.
It turns out that the code snippet I posted had nothing to do with the deadlock problem. The deadlock was occuring during a "roll-up" of information down the organization hierarchy. This roll-up was obtaining locks on each and every organization involved in the summation, and holding them until the entire summation was done. In addition, some methods in both the Organization class as well as the DAO were needlessly synchronized, so it was possible for the Organization<=>DAO interaction to lock different resources in different orders. Thus, if two or more users attempted to perform a roll-up under the right timing conditions, deadlock was bound to happen. These locks were for the most part unnecessary, and I reduced the locking in a manner similar to the code snippet I posted.
Thanks again,
Jason
[ February 26, 2003: Message edited by: Jason Voegele ]
15 years ago

Originally posted by Robert Paris:
Well, I don't know your problem but I do have a problem with this:

Not true. Only sometimes. Remember, depending on the scope of your object, it may not need ANY thread safety. Scope is what matters here and I don't know what the scope would be of your object in the application you have. Is it's scope request? If so, then there's no need to synchronize it. Check that first.


True, my wording was sloppy. I should have explicitly mentioned shared mutable data. And the fields that I am working with are in fact shared and mutable.
[ February 21, 2003: Message edited by: Jason Voegele ]
15 years ago
Hello Ranchers,
I've developed a Web application that is currently experiencing some problems with thread deadlock. After reviewing some of the code that (I suspect) is causing the deadlock, I noticed that many methods were either unnecessarily synchronized or where the synchronization could be done in a finer grained manner. I've fixed many such problems by implementing finer-grained synchronization (i.e. locking only a subset of the fields of the object, rather than the entire object).
However, now I've come across a scenario that I'm not sure quite how to handle. As I'm sure you know, it is necessary to synchronize access/modification of mutable fields of an object. Another rule is that you should (almost) never call a method on an external object from within a synchronized block or method. This raises a problem for my system due to the use of lazy initialization of data that is gathered from a database.
Consider this example. I have a class called Organization that represents a single organization within some company. One of the methods in the Organization class is called getEmployees(), which returns a list of all employees working in that organization. This method uses lazy initialization to defer the construction of the list of employees until the first time the method is called. My original implementation looked like this:

I then refactored the method to use finer-grained locking:

This is an improvement in the sense that it does not lock the entire Organization object while the data is being loaded from the database.
However, this method violates the (well-publicized) rule that you should (almost) never invoke a method on an external object (such as the DAO) from within a synchronized block. And indeed, it is the violation of this rule that is causing the deadlock in this system.
I've considered the following solution:

However, this is not a viable solution since another thread could come in and initialize the employees field between the two synchronized blocks.
Sorry for the length of this post, but does anyone have any ideas for a good solution to this problem?
Thanks,
Jason Voegele
[ February 21, 2003: Message edited by: Jason Voegele ]
15 years ago

Originally posted by Mark Spritzler:

The is absolutely NO LOCKING in local mode. In local mode the app has exclusivity to the Data classes and db.db file.


Do you say this because you think it implies a complication in design, or that it's a waste of resources, or both?
As for the first point (complicated design), I don't think it's necessarily an issue. I've implemented a LockManager that has two methods:
public void lock(int record, Object lockHolder);
and
public void unlock(int record, Object lockHolder);
In remote mode, calls to these lock and unlock methods are called from the "Connection" object like this:
lockManager.lock(myRecord, this);
In local mode, I can use this same LockManager class and call the methods from Data.java like so:
lockManager.lock(myRecord, Thread.currentThread());
I really like this approach, and I think it is one of those situations (like implementing Unreferenced for connections) where you get much improved functionality basically for free. Why
not add it?
If you feel that it is simply a waste of resources to implement locking in local mode, I counter with the fact that the database is intended to be reused by other applications and we cannot predict whether or not those applications would require multi-threaded access.
I, for one, will be implementing locking in local mode. As I've said, if you modularize your code appropriately, you get it basically for free anyway.
Your thoughts?
Jason Voegele

Originally posted by Peter den Haan:

Singleton is appropriate wherever there is a fundamental reason why you cannot or should not have more than one copy of an object.
Is there any fundamental reason why you cannot or should not have more than one Data? Well, to the contrary, I'd say.


In my implementation I'm using two static factory methods in Data.java: one called open, the other called create. These methods use a HashMap that contains previously created instances of class Data, keyed by a File object representing the file containing the database. This scheme ensures that only one instance of class Data exists per file within a single JVM. This is of course a variant of the Singleton pattern, and one which I think applies to Data.
What do you think?
-- Jason Voegele
Congratulations, Gennady! That's an excellent score.
You are the first person I've seen that got a perfect score on the server piece. Would you care to summarize the design of your server?
Jason Voegele
------------------

Originally posted by Mark Spritzler:
Jason, the connection object is not bound to the Registry. If that helps out, the other thing to check out is O-Reilly's book on RMI. That is how I got over the same question that you have.


Ah...that does make more sense. I was assuming that the Connection object was looked up by name from the client. Since that is not the case, this makes more sense now.
Thanks.

Originally posted by Peter den Haan:
[B]A particularly elegant solution is to give each client its own Connection remote object that implements the DataInterface. This solves all your problems in one go without unnecessarily burdening the client code with tokens, additional arguments or whatever. After all, the Connection on which the method (lock, unlock, add,...) is invoked is the client identity you're looking for.


I'm a bit confused by this. If the Connection object is a true remote object, then the semantics of remote objects dictate that there is one copy of the Connection object, not one per client. Could you expound upon this?
Thanks,
Jason Voegele