This week's book giveaway is in the OCAJP forum. We're giving away four copies of OCA Java SE 8 Programmer I Study Guide 1Z0-808 and have Jeanne Boyarsky & Scott Selikoff on-line! See this thread for details.
I have a basic data class Customer which has 4 fields, LastName, FirstName, UserID, and TransactionNo
My RMI setup is as follows:
Client takes LastName and FirstName as arguments and gets the UserID and TransactionNo programmatically
The Client looks like the following: <After connecting to the server>
The ServerImpl can process the data from the Client and looks like:
The problem that I am having is that if I instance two Clients and make each Client instance loop around 1000 time, most of the time I will get what I expect:
Before : Client A�s data After : Client A�s data
Every so often though, I will see: Before : Client A�s data After : Client B�s data
This happened whether I synchronized on the SetGet function or on the customer object. (The code shows it both ways)
More detailed logging of ServerImpl indicates that where the problems appear (I can tell by the TransNo) after entering the synchronized block or function, the block or function is interrupted by the other Client.
It took me a while to recreate your problem, but I finally did. The synchronization is not really the problem. I did tests and I did not see an instance in which two Threads had access to the Server.customer at one time. Where the problem comes in is that you are returning a reference to the Server.customer. This same reference is then locked by the next Thread that tries to access the GetSet method. The problem is that on the client, you use the same reference. Scenario:
1. Client 1 calls GetSet() 2. GetSet() returns with Server.customer reference, values set to Client 1 3. Context switch to Client 2. 4. Client 2 calls GetSet() 5. GetSet() returns with Server.customer reference, values set to Client 2 6. Context switch to Client 1. 7. Client 1 prints customer.toString() with values from Client 2 because customer in Client 1 holds the same reference, but with updated content.
My solution was to make Customer implement Cloneable and return a clone of Customer from getCustomer(). I'll put all my code in here...