I have the following class which contains only one field i. Access to this field is guarded by the lock of the object ("this"). When implementing equals() I need to lock this instance (a) and the other (b). If thread 1 calls a.equals(b) and at the same time thread 2 calls b.equals(a), the locking order is reverse in the two implementations and may result in deadlock.
How should I implement equals() for a class which has synchronized fields?
public class Sync {
// #GuardedBy("this")
private int i = 0;
public synchronized int getI() {return i;}
public synchronized void setI(int i) {this.i = i;}
public int hashCode() {
final int prime = 31;
int result = 1;
synchronized (this) {
result = prime * result + i;
}
return result;
}
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Sync other = (Sync) obj;
synchronized (this) {
synchronized (other) {
// May deadlock if "other" calls
// equals() on "this" at the same
// time
if (i != other.i)
return false;
}
}
return true;
}
}
Trying to synchronize equals and hashCode inside the object will not work properly. Consider the case of a HashMap that uses hashCode to discover which "bucket" an object will be in, and then uses equals to sequentially search all objects in the bucket.
If objects are allowed to mutate in a way that changes the outcomes of hashCode or equals you could end up with a scenario where HashMap calls hashCode. It acquires the lock, gets the hash and releases the lock again. HashMap then proceeds to compute which "bucket" to use. But before HashMap can acquire the lock on equals someone else grabs the lock and mutates the object so that equals become inconsistent with the previous value of hashCode. This will lead to catastrophic results.
The hashCode and equals methods are used in a lot of places and is core to the Java collections API. I might be valuable to rethink your application structure that do not require synchronized access to these methods. Or at the very least not synchronize on the object itself.
Why synchronise? What is the use case where it matters one if them changes during the comparison and it does not matter if if changes immediately after before code depending on equality runs. (ie if you have code depending on equlity what happens if the values become unequal before or during this code)
I think you have to take a look at the larger process to see where you need to lock.
Where is the point in synchronizing equals() if the result isn't guaranteed to be true after synchronization was left:
if (o1.equals(o2)) {
// is o1 still equal to o2?
}
Hence you could simply synchronize calls to getI() inside equals one after another without changing the output - it's simple not valid anymore.
You'll always have to synchronize the whole block:
synchronized(o1) {
synchronized(o2) {
if (o1.equals(o2)) {
// is o1 still equal to o2?
}
}
}
Admittedly, you'll still face the same problem, but at least your synchronizing at the right point ;)
If it has been said enough, the fields you use for hashCode(), equals() or compareTo() should be immutable, preferably final. In this case you don't need to synchronise them.
The only reason to implement hashCode() is so the object can be added to a hash collection, and you cannot validly change the hashCode() of an object which has been added to such a collection.
You are attempting to define a content-based "equals" and "hashCode" on a mutable object. This is not only impossible: it doesn't make sense. According to
http://java.sun.com/javase/6/docs/api/java/lang/Object.html
both "equals" and "hashCode" need to be consistent: return the same value for successive invocations on the same object(s). Mutability by definition prevents that. This is not just theory: many other classes (eg collections) depend on the objects implementing the correct semantics for equals/hashCode.
The synchronization issue is a red herring here. When you solve the underlying problem (mutability), you won't need to synchronize. If you don't solve the mutability problem, no amount of synchronization will help you.
(I assume that you're interested in the general case here, and not just in wrapped integers.)
You can't prevent two threads from calling set... methods in arbitrary order. So even when one thread gets a (valid) true from calling .equals(...), that result could be invalidated immediately by another thread that calls set... on one of the objects. IOW the result only means that the values were equal at the instant of comparison.
Therefore, synchronizing would protect against the case of the wrapped value being in an inconsistent state while you are attempting to do the compare (e.g. two int-sized halves of a wrapped long being updated consecutively). You could avoid a race condition by copying each value (i.e. independently synchronized, without overlap) and then comparing the copies.
The only way to know for sure if synchronization is strictly necessary is to analyze the entire program for situations. There are two things you need to look for; situations where one thread is changing an object while another is calling equals, and situations where the thread calling equals might see a stale value of i.
If you lock both this and the other object at the same time you do indeed risk a deadlock. But I'd question that you need to do this. Instead, I think you should implement equals(Object) like this:
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Sync other = (Sync) obj;
return this.getI() == other.getI();
}
This does not guarantee that the two objects have the same value of i at the same time, but that is unlikely to make any practical difference. After all, even if you did have that guarantee, you'd still have to cope with the issue that the two objects might no longer be equal by the time that the equals call returned. (This is #s's point!)
Furthermore, this does not entirely eliminate the risk of deadlock. Consider the case where a thread may call equals while holding a lock on one of the two objects; e.g.
// In same class as above ...
public synchronized void frobbitt(Object other) {
if (this.equals(other)) {
...
}
}
Now if two threads call a.frobbitt(b) and b.frobbitt(a) respectively, there is a risk of deadlock.
(However, you do need to call getI() or declare i to be volatile, otherwise the equals() could see a stale value of i if it was recently updated by a different thread.)
This having been said, there is something rather worrying about a value-based equals method on an object whose component values may be mutated. For example, this will break many of the collection types. Combine this with multi-threading and you are going to have a lot of difficulty figuring out whether your code is really correct. I cannot help thinking that you would be better off changing the equals and hashcode methods so that they don't depend on state that may mutate after the methods have been called the first time.
Always lock them in the same order, one way you could decide the order is on the results of System.identityHashCode(Object)
Edit to include comment:
The best solution to deal with the rare case of the identityHashCodes being equal requires more details about what other locking of those objects is going on.
All multiple object lock requirements should use the same resolution process.
You could create a shared utility to track objects with the same identityHashCode for the short period of the lock requirements, and provide a repeatable ordering for them for the period that they're being tracked.
The correct implementation of equals() and hashCode() is required by various things like hashing data structures, and so you have no real option there. From another perspective, equals() and hashCode() are just methods, with the same requirements on synchronization as other methods. You still have the deadlock problem, but it's not specific to the fact that it equals() that's causing it.
As Jason Day points out, integer compares are already atomic, so synchronizing here is superfluous. But if you were just constructing a simplified example and in real life you're thinking of a more complex object:
The direct answer to your question is, insure that you always compare the items in a consistent order. It doesn't matter what that order is, as long as it's consistent. In a case like this, System.identifyHashCode would provide an ordering, like:
public boolean equals(Object o)
{
if (this==o)
return true;
if (o==null || !o instanceof Sync)
return false;
Sync so=(Sync) o;
if (System.identityHashCode(this)<System.identityHashCode(o))
{
synchronized (this)
{
synchronized (o)
{
return equalsHelper(o);
}
}
}
else
{
synchronized (o)
{
synchronized (this)
{
return equalsHelper(o);
}
}
}
}
Then declare equalsHelper private and let it do the real work of comparing.
(But wow, that's a lot of code for such a trivial issue.)
Note that for this to work, any function that can change the state of the object would have to be declared synchronized.
Another option would be to synchronize on Sync.class rather than on either object, and then to also synchronize any setters on Sync.class. This would lock everything on a single mutex and avoid the whole problem. Of course, depending on what you're doing this might cause undesired blocking of some threads. You'd have to think through the implications in light of what your program is about.
If this is a real issue in a project you're working on, a serious alternative to consider would be to make the object immutable. Think of String and StringBuilder. You could create a SyncBuilder object that lets you do any work you need to create one of these things, then have a Sync object whose state is set by the constructor and can never change. Create a constructor that takes a SyncBuilder and sets its state to to match or have a SyncBuilder.toSync method. Either way, you do all your building in SyncBuilder, then turn it into a Sync and now you're guaranteed immutability so you don't have to mess with synchronization at all.
Do not use syncs. Think about unmodifiable beans.
You need to make sure the objects do not change between the calls to hashCode() and equals() (if called). Then you must assure that the objects do not change (to the extend that hashCode and equals are concerned) while the object sits in a hashmap. To change the object you must first remove it, then change it and put it back.
As others have mentioned, if things change during the equals check, there is already a possibility of crazy behavior (even with correct synchronization). so, all you really need to worry about is visibility (you want to make sure a change which "happens before" your equals call is visible). therefore, you can just do "snapshot" equals which will be correct in terms of "happens before" relationship and will not suffer from lock ordering problems:
public boolean equals(Object o) {
// ... standard boilerplate here ...
// take a "snapshot" (acquire and release each lock in turn)
int myI = getI();
int otherI = ((Sync)o).getI();
// and compare (no locks held at this point)
return myI == otherI;
}
Reads and writes to int variables are already atomic, so there is no need to synchronize the getter and setter (see http://java.sun.com/docs/books/tutorial/essential/concurrency/atomic.html).
Likewise, you don't need to synchronize equals here. While you could prevent another thread from changing one of the i values during comparison, that thread would simply block until the equals method completes and change it immediately afterwards.
Related
I'm using a custom class Foo in Java as the key type in a HashMap. All the fields of Foo instances are immutable (they are declared final and private and are assigned values only in the constructor). Thus, the hashCode() of a given Foo object is also fixed, and for optimization purposes, I am calculating it in the constructor and simply returning that value in the hashCode() method.
Instances of Foo also have a value() method which returns a similar fixed value once the object has been instantiated. Currently I am also calculating it in the constructor and returning it in the method, but there is a difference between hashCode() and value(): hashCode() is called for the first time almost instantly after the object is created, but value() is called much later. I understand that having a separate Thread to calculate the hash-code would simply increase the run-time because of synchronization issues, but:
is this a good way to calculate value()? Would it improve run-time at all?
are simple Threads enough, or do I need to use pools etc.?
Note: this may seem like I'm optimizing the wrong parts of my program, but I've already worked on the 'correct' parts and brought the average run-time down from ~17 seconds to ~2 seconds. Edit: there will be upwards of 5000 Foo objects, and that's a conservative estimate.
It definitely sounds like deferred calculation is a good approach here - and yes, if you create a lot of these objects, a thread pool is the way to go.
As for value()'s return value until it's ready, I would stay away from returning invalid values, and instead either make it blocking (and add some isValueReady() helper) or make it instantly return a "future" - some object that offers those same isReady and a blocking get methods.
Also, never rely on "much later" - always make sure the value there is ready before using it.
I recommend creating a Future for value - create a static fixedTheadPool and submit the value calculations on it. This way there's no risk that value will be accessed before it's available - the worst case is that whatever is accessing value will block on a Future.get call (or use the version with a timeout if e.g. deadlock is a concern)
Because Future.get throws checked exceptions which can be a nuisance, you can wrap the get call in your class's getter method and wrap the checked exceptions in a RuntimeException
class MyClass {
private static final ExecutorService executor = Executors.newFixedThreadPool(/* some value that makes sense */);
private final Future<Value> future;
public MyClass() {
future = executor.submit(/* Callable */);
}
public boolean isValueDone() {
return future.isDone();
}
public Value value() {
try {
return future.get();
} catch(InterruptedException|ExecutionException e) {
throw new RuntimeException(e);
}
}
}
I need to make the following class thread-safe:
//Shared among all threads
public class SharedCache {
private Map<Object, Future<Collection<Integer>>> chachedFutures;
{
chachedFutures = new ConcurrentHashMap<>(); //not sure about that
}
public Future<Collection<Integer>> ensureFuture(Object value,
FutureFactory<Collection<Integer>> ff){
if(chachedFutures.containsKey(value))
return chachedFutures.get(value);
Future<Collection<Integer>> ftr = ff.create();
chachedFutures.put(value, ftr);
return ftr;
}
public Future<Collection<Integer>> remove(Object value){
return chachedFutures.remove(value);
}
}
After reading the article about the ConcurrentHashMap class it's still difficult for me to make a right decision.
Firstly, I tended to make the methods ensureFuture and remove just synchronized. And it would work, but from the performance standpoint it was not very good because of mutually-exclusing.
I don't know the exact (even approximately) amount of threads having access to the Cache simultaneously and the size of the Cache. Taking into account that
resizing this or any other kind of hash table is a relatively slow
operation
I didn't specify the initial size of the map. Also the concurrencyLevel parameter. Is it justified to use ConcurrentHashMap here or synchronized methods would be enough?
You have following methods:
public Future<Collection<Integer>> ensureFuture(Object value,
FutureFactory<Collection<Integer>> ff){
if(chachedFutures.containsKey(value))
return chachedFutures.get(value);
Future<Collection<Integer>> ftr = ff.create();
chachedFutures.put(value, ftr);
return ftr;
}
public Future<Collection<Integer>> remove(Object value){
return chachedFutures.remove(value);
}
There are some points to be noticed:
Suppose method ensureFuture is not synchronized in that case it is possible that one thread invokes containsKey which returns true but before next line is executed another thread may remove the entry respective to that key. This can lead to race condition as it is check-then-act scenario. Check this as well.
Also you are using chachedFutures.put(value, ftr) but IMO you should use chachedFutures.putIfAbsent(value, ftr) . For this method if the specified key is not already associated with a value (or is mapped to null) associates it with the given value and returns null, else returns the current value. Using this you can also avoid contains check.
Is it justified to use ConcurrentHashMap here or synchronized methods
would be enough?
It depends as CHM needs more memory compared to HashMap due to lot of bookkeeping activities etc. Another alternative is to use Collections.synchronizedMap which will provide synchronization on a regular HashMap.
I came across the example below of a Java class which was claimed to be thread-safe. Could anyone please explain how it could be thread-safe? I can clearly see that the last method in the class is not being guarded against concurrent access of any reader thread. Or, am I missing something here?
public class Account {
private Lock lock = new ReentrantLock();
private int value = 0;
public void increment() {
lock.lock();
value++;
lock.unlock();
}
public void decrement() {
lock.lock();
value--;
lock.unlock();
}
public int getValue() {
return value;
}
}
The code is not thread-safe.
Suppose that one thread calls decrement and then a second thread calls getValue. What happens?
The problem is that there is no "happens before" relationship between the decrement and the getValue. That means that there is no guarantee, that the getValue call will see the results of the decrement. Indeed, the getValue could "miss" the results of an indefinite sequence of increment and decrement calls.
Actually, unless we see the code that uses the Account class, the question of thread-safety is ill-defined. The conventional notion of thread-safety1 of a program is about whether the code behaves correctly irrespective of thread-related non-determinacy. In this case, we don't have a specification of what "correct" behaviour is, or indeed an executable program to test or examine.
But my reading of the code2 is that there is an implied API requirement / correctness criterion that getValue returns the current value of the account. That cannot be guaranteed if there are multiple threads, therefore the class is not thread-safe.
Related links:
http://blogs.msdn.com/b/ericlippert/archive/2009/10/19/what-is-this-thing-you-call-thread-safe.aspx
1 - The Concurrency in Practice quote in #CKing's answer is also appealing to a notion of "correctness" by mentioning "invalid state" in the definition. However, the JLS sections on the memory model don't specify thread-safety. Instead, they talk about "well-formed executions".
2 - This reading is supported by the OP's comment below. However, if you don't accept that this requirement is real (e.g. because it is not stated explicitly), then the flip-side is that behaviour of the "account" abstraction depends on how code outside of the Account class ... which makes this a "leaky abstraction".
This is not thread safe purely due to the fact there is no guarantees about how the compiler can re-order. Since value is not volatile here is your classic example:
while(account.getValue() != 0){
}
This can be hoisted to look like
while(true){
if(account.getValue() != 0){
} else {
break;
}
}
I can imagine there are other permutations of compiler fun which can cause this to subtly fail. But accessing this getValue via multiple threads can result in failure.
There are several distinct issues here:
Q: If multiple threads make overlapped calls to increment() and decrement(), and then they stop, and then enough time passes with no threads calling increment() or decrement(), will getValue() return the correct number?
A: Yes. The locking in the increment and decrement methods insures that each increment and decrement operation will happen atomically. They can not interfere with one another.
Q: How long is enough time?
A: That's hard to say. The Java language specification does not guarantee that a thread calling getValue() will ever see the latest value written by some other thread because getValue() accesses the value without any synchronization at all.
If you change getValue() to lock and unlock the same lock object or if you declare count to be volatile, then zero amount of time would be enough.
Q: Can a call to getValue() return an invalid value?
A: No, It can only ever return the initial value, or the result of complete increment() call or the result of a complete decrement() operation.
But, the reason for this has nothing to do with the lock. The lock does not prevent any thread from calling getValue() while some other thread is in the middle of incrementing or decrementing the value.
The thing that prevents getValue() from returning a completely invalid value is that value is an int, and the JLS guarantees that updates and reads of int variables are always atomic.
The short answer :
By definition,Account is a thread-safe class even though the geValue method is not guarded
The long answer
From Java Concurrency in practice a class is said to be thread safe when :
No set of operations performed sequentially or concurrently on
instances of a thread-safe class can cause an instance to be in an
invalid state.
Since the the getValue method will not result in the Account class being in an invalid state at any given time, your class is said to be thread safe.
The documentation for Collections#synchronizedCollection resonates this sentiment :
Returns a synchronized (thread-safe) collection backed by the
specified collection. In order to guarantee serial access, it is
critical that all access to the backing collection is accomplished
through the returned collection. It is imperative that the user
manually synchronize on the returned collection when iterating over
it:
Collection c = Collections.synchronizedCollection(myCollection);
...
synchronized (c) {
Iterator i = c.iterator(); // Must be in the synchronized block
while (i.hasNext())
foo(i.next());
}
Notice how the documentation says that the collection (which is an object of an inner class named SynchronizedCollection in the Collections class) is thread-safe and yet asks the client code to guard the collection while iterating over it. Infact, the iterator method in SynchronizedCollection is not synchronized. This is very similar to your example where Account is thread-safe but client code still needs to ensure atomicity when calling getValue.
It's completely thread safe.
Nobody can simultaneously increment and decrement value so you won't lose or gain a count in error.
The fact that getValue() will return different values through time is something that will happen anyway: simultaneity is not relevant.
You do not have to protect getValue. Accessing it from multiple threads at the same time does not lead to any negative effects. The object state cannot become invalid no matter when or from how many threads you call this methid (because it does not change).
Having said that - you can write a non-thread-safe code that uses this class.
For example something like
if (acc.getValue()>0) acc.decrement();
is potentially dangerous because it can lead to race conditions. Why?
Let's say you have a business rule "never decrement below 0", your current value is 1, and there are two threads executing this code. There's a chance that they'll do it in the following order:
Thread 1 checks that acc.getValue is >0. Yes!
Thread 2 that acc.getValue is >0. Yes!
Thread 1 calls decrement. value is 0
Thread 2 calls decrement. value is now -1
What happened? Each function made sure it was not going below zero, but together they managed to do that. This is called race condition.
To avoid this you must not protect the elementary operations, but rather any pieces of code that must be executed uninterrupted.
So, this class is thread-safe but only for very limited use.
Suppose you have a written a class and have used lazy initialization to assign one of its fields. Suppose that the computation for that field only involves the other fields and is guaranteed to produce the same result every time. When two equal instances of the class encounter one another, it makes sense for them to share the value of the lazily initialized field (if either knows it). You could do this in the equals() method. Here is a class showing what I mean.
final class MyClass {
private final int number;
private String string;
MyClass(int number) {
this.number = number;
}
String getString() {
if (string == null) {
string = OtherClass.expensiveCalculation(number);
}
return string;
}
#Override
public boolean equals(Object object) {
if (object == this) { return true; }
if (!(object instanceof MyClass)) { return false; }
MyClass that = (MyClass) object;
if (that.number != number) { return false; }
String thatString = that.string;
if (string == null && thatString != null) {
string = thatString;
} else if (thatString == null && string != null) {
that.string = string;
}
return true;
}
#Override
public int hashCode() { return number; }
}
To me, this information-sharing seems the logical thing to do if you are going to go to the effort of lazily initializing a field, yet I have never seen an example of anyone using the equals() method in this way.
Is it a common or standard technique? If so, what is it called? If it is not a common technique, can I ask (at the risk of having the question put on hold as primarily opinion-based) what people think about it? Is it a good idea to use the equals() method to do anything other than check for equality?
This looks dangerous to me: the use of a side affect of a public method of Object to set an object's state. This will break if you subclass this class, and then override the subclass's equals method, a common thing to do. Just don't do this.
"Suppose that the computation for that field only involves the other fields and is guaranteed to produce the same result every time."
Given this supposition, you can assert that the value of the lazily initialized field does not matter because if the values of the other fields are the same, the calculated value will also be the same.
Edit
I guess I sidestepped the original question, so I'll answer that too. In the scenario you've created, there is nothing inherently wrong with what you're proposing.
The argument I would make is simply from a pragmatic standpoint: what happens when someone else is changing the definition of getString() (or more likely - changing the definition of the long running calculation that results in that value) and it starts relying on something that's not part of the object's equality considerations?
The reason conventional wisdom says that equals() should be side effect free is that most developers expect it to be side effect free.
I would not do this, for three reasons:
General software-engineering principles, such as cohesion, loose coupling, and "don't repeat yourself", militate against it: your equals(...) method will be doing something not very "equals"-y, that overlaps with the logic of your getString() method. Someone updating the logic of getString() might well fail to notice if they also need to update the logic of equals(...). (You might think that the logic of equals(...) will continue to be correct no matter how getString() is changed — after all, you're just having equals(...) copy the reference from one object to an equivalent one, so presumably that should always stay the same? — but the problem is that complex systems evolve in ways that you can't always predict in advance. When a requirement changes, you don't want to have make random changes in parts of the code that aren't obviously related to the requirement.)
Thread-safety. Your string field currently isn't volatile, and your getString() method currently isn't synchronized, so there's no attempt at thread-safety here anyway; but if you were to make the rest of the class thread-safe, it would not be perfectly straightforward to change equals(...) to be thread-safe without risking deadlocks. (This overlaps a bit with point #1, but I'm listing it separately because #1 is solely about the difficulty of knowing that you have to change equals(...), whereas this issue is a bit tricky to address even given that knowledge.)
Unlikelihood of usefulness. There's not much reason to expect it to happen very often that two instances get equals(...)-compared when one has already been lazy-initialized and the other has not; so the extra code complexity, and downsides mentioned above, are not likely to be worth it. (Remember: code is not free. In order to pass cost–benefit analysis, the benefits of a piece of code must exceed the costs of testing, understanding, maintaining, and supporting it in the future.) If it's worthwhile to share these lazy-initialized values between equivalent instances, then that should be done in a clearer and more-organized fashion that does not rely on happenstance. (For example, you might make the class's constructor private, and have a static factory-method that checks a static WeakHashMap for an existing instance before creating and returning a new one.)
The approach you describe is sometimes a good one, especially in situations where it is likely that many large immutable objects, despite being independently constructed, will end up being identical. Because it is much faster to compare equal references than to compare large objects which happen to be equal, it may be advantageous to have code which compares two large-objects and finds them to be identical replace one of the references with a reference to the other. For this to be workable, one should attempt to establish some sort of ordering among the objects in question to ensure that repeated comparisons will eventually yield the same canonical value. This could be accomplished by having objects include a long sequence number and consistently replacing references to newer values with references to older-but-equal values, or by comparing the identityHashCode value of the equal references and discarding whichever one, if any, has the lower value (if two references which identify distinct but identical instances, happen to report the same identityHashCode, both should be kept).
A nasty but unfortunate wrinkle in this is that Java has very poor multi-threading support for effectively-immutable objects. For an effectively-immutable object to be thread-safe, any access to an array or non-final field must go through a final field. The cheapest way of accomplishing that is probably to have the object contain a final field into which it stores a reference to itself, and have all methods which access non-final fields do so through that final field, but that's a bit ugly. Still, changing references distinct-but-identical references with references to the same object could offer some significant performance advantages despite the silly redundant final field accesses (since the target of the final field would be guaranteed to be in-cache, dereferencing it would be much cheaper than a normal dereference).
BTW, it would in many cases be possible to include an "equivalence-relation" mechanism such that once some objects were compared and found to be equal, discovering that any of them is equal to another object would cause all of them to be quickly recognizable as such. I haven't figured out how to avoid the possibility of a deliberately-nasty-but-legitimate usage pattern causing a memory leak, however.
In the following code snippet, why is it desirable to return a copy of data[i]. What exactly happen in a multi-threaded environment if copy is not made.
protected Object[] data;
..
public synchronized Object get(int i)
throws NoSuchElementException
{ if (i < 0 || i >= size )
throw new NoSuchElementException();
return data[i];
}
why is it desirable to return a copy of data[i].
You're returning a copy of the reference at index i, not a copy of the object.
Unless you create a copy of the object through for instance data[i].clone(), you'll always have a single object and share references to it among your threads. There is nothing wrong with sharing references to a single object among several threads.
What exactly happen in a multi-threaded environment if copy is not made.
Well, unless you synchronize your threads using the synchronized methods, wait/notify or the java.util.concurrent-classes you may end up with race-conditions. A race condition is basically a situation where the result of the execution is dependent on the particular scheduling (the order in which the threads may execute).
If you share objects of a certain class among threads, you should design it to be "thread safe". If your object represents a value object I recommend you to make it immutable.
Well, I see nothing wrong with the method as it is - it is not making a copy. It depends on what are you planning to do with the returned object after. If you will be modifying it from different threads, then it is a good idea to return a copy for each thread.
Since the method is synchronized and unless nobody else in the same package manipulates the data array there should be no multi-threaded issues.
Because it could be more comfortable for the calling code. If you don't return a copy (as shows your example) you have to synchronize on the returning reference (data[i]) if you want to avoid race conditions.
desirable to return a copy of data[i]
Since your get() is synchronized it is likely that several threads will access the objects in parallel. Now this will lead to problems if the following points are true
the objects stored in the array are muteable (can change state)
the objects methods are not synchronized (the object is not threadsafe)
If these are true you could end up with objects in an invalid state if two threads manipulate the objects at the same time. Creating a copy of the objects prevents this, since every thread will handle its own copy.
With multiple threads having direct access to the same object, you can get issues with unexpected behavior.
Consider the following:
Thread A:
Object foo = get(1);
foo.member += 5;
Thread B:
Object bar = get(1);
bar.member = 2;
Assuming these 2 threads are running simultaneously, you have no way of knowing what the end state of the object stored in data[1] will be. The point at which threads switch control isn't predictable, and while you might be fine 99% of the time, your code can be open to intermittent bugs.
What you would really want to do is protect any methods that modify the state of the objects data[] with the "synchronized" key word. Getters, setters, etc should all be synchronized. Having a synchronized method which just hands out references to objects is pointless.
Please do not use clone to create copy , it has its own faults. use copy constructor or create a new object and set the member values and return the same.