Using variable reference to point to static member of some other class - java

I have a class Cache which picks up List<SomeObject> someObjectList from DB and stores it in static variable.
Now I have another thread A which uses this List as follows
class A extends Thread{
private List<SomeObject> somobjLst;
public A(){
somobjLst = Cache.getSomeObjectList();
}
void run(){
//somobjLst used in a loop here, no additong are done it , but its value is used
}
}
Now if at some point of time if some objects are added to Cache.someObjectList will it reflect in class A. I think it should as A only holds a refrence to it.
Will there will be any problem in A's code when content of Cache.someObjectList change?
EDIT:
As per suggestions :
if i make
void run (){
while(true){
synchronized(someObjList){
}
try{
Thread.sleep(INTERVAL);
}catch(Exception e){
}
}
}
will this solve problem?

Yes, the changes will be reflected in class A as well. Exactly as you say: A holds a reference to the exact same object as Cache.
Yes, it can lead to a problem if A doesn't expect it to change. It also can lead to a problem if the List implementation is not thread safe (most general-purpose implementations are not thread-safe!). Accessing a non-thread-safe data structure from two threads at the same time can lead to very nasty problems.

Sure, you are holding reference to collection in your thread. If collection is changed while you are iterating over it in thread ConcurrentModificationException will be thrown.
To avoid it you have to use some kind of synchronization mechanism. For example synchronize the iteration over collection and its modification done in other thread using synchronize(collection).
This is a kind of "pessimistic" locking.
Other possibility is to use collections from java.util.concurrent package.

Related

Is the following code threadsafe?

I see the following example in Java Concurrency in Practice book, and it is mentioned that the class is threadsafe, and there is no information given about Person class. If the person class is mutable, then after adding a Person Object, it can be modified, say value that is used in equals method may be modified by another thread, in that case the following code will not be threadsafe. Is that correct statement?
#ThreadSafe
public class PersonSet {
#GuardedBy("this")
private final Set<Person> mySet = new HashSet<Person>();
public synchronized void addPerson(Person p) {
mySet.add(p);
}
public synchronized boolean containsPerson(Person p) {
return mySet.contains(p);
}
}
Yes it is thread safe. Thread safe in the sense that only one thread at a time can do read on set via containsPerson method or may be able to add set via addPerson method.
This class is thread safe because it has one Object state i.e. Set it self. So it protects it's state by allowing only one thread to work upon it.
However it doesn't guarantee that Person can't be modified by multiple thread. If you want to achieve the same you can either create Person as immutable object or you make it thread safe as well i.e. allow only one thread to modify it's state.
Your statement is correct: if the Person class is mutable, and an update is done on a field that contributes to hashCode and equals, then the PersonSet will have a problem - no matter in which thread.
The no duplicate Set contract will be broken, silently...
here object lock(this) is being used . the object which was used to access methods of personSet class which is of personSet type ,No two threads can access any of methods of personSet at one time. In locking there is no dependency of Person class. So personSet class is thread safe.
The thread safety in question here only pertains to the set, not the contents of the set. There are no allowances or checks made on a retrieval (i.e. get) operation on the set, so that portion is thread unsafe. Since that's not exposed, then the operations of adding and checking to see if an element is contained in the set are indeed thread-safe.
Note that while these operations are indeed safe for threads, they're also not concurrent. Since synchronized will block multiple threads from interacting with the method at once, these methods will become a bottleneck if used in a highly concurrent environment.

Can't synchronize (java.util.ConcurrentModificationException)

I have the following Java code:
private Object guiUpdateLock = new Object();
public void updateLinkBar(SortedSet<Arbitrage> arbitrages) {
synchronized (guiUpdateLock) {
System.out.println("start");
for (Arbitrage arbitrage : arbitrages) {
//do some GUI stuff
}
System.out.println("end");
}
}
updateLinkBar() is called from many threads, and occasionally I get java.util.ConcurrentModificationException in "for" cycle.
But I can't understand why since I'm making a lock on object which obviously doesn't work because I can see two "start" in a row in the output.
Thank you in advance.
Locks must protect objects and not segments of code.
In your case you accept an arbitrary collection, acquire your private lock, and operate on the collection. Meanwhile the rest of your code may, in other threads, do whatever it wants with the collection and it doesn't have to contend for your private lock to do it.
You must significantly redesign your code such that all access to the collection in question is covered by the same lock.
Without your complete code I have to resort to guessing, but the most likely case is that the two threads are using different guiUpdateLog-Objects to synchronize on. My further guessing would be that they are using different instances of the class that contains the guiUpdateLock - and since it is not static there will be different Object-instances as well.

how to locally synchronize two maps?

For instance,
class Test{
static Map a = new ...
static Map b = new ...
public void process(){
...
a.put(...);
b.put(...);
}
}
Do I have to lock like this:
synchronized(a){
a.put();
}
synchronized(b){
b.put(b);
}
This seems to be awkward. Any other right way to do this? Thanks.
No, you need both operations in one synchronized block, otherwise another thread may see inconsistencies between the two maps.
One possible option would be using a synchronized method, or you could use some other private object or one of the maps as an monitor. Here is the synchronized method example:
static Map a = new ...
static Map b = new ...
public synchronized void process(){
...
a.put(...);
b.put(...);
}
}
You can use a dedicated object like
Object mapLock = new Object();
to synchronize on.
Or you can sync on a keeping in mind that even if you need an access to b you need to sync on a.
Synchronizing on this is not a good idea in general. I mean this is a bad habit and doing so may eventually result in bad performance or non-obvious deadlocks if not in this but other applications you make.
Avoid synchronized(this) in Java?
You can also consider using ReadWriteLock from concurrency package.
You do need to run both operations within one synchronized block. Worth noting that in your example, you've defined the maps statically while the process() method is an instance method. The synchronizing the method will mean that calls to that instance will be synchronized, but that calls to 2 different instances will not (as the lock used when applying the synchronized keyword to a method is effectively this). You could either make the process() method static, or use a synchronized(Test.class) {} block instead to ensure that there's no racing happening.
You will also need to be careful about how you expose the maps to clients - if you're offering them up as properties, then I would probably wrap them with Collections.unmodifiableMap() to ensure that nothing else can go and screw with them while you're not looking - however that doesn't entirely protect against clients having an "odd" time as they will still see changes happen in potentially unsafe ways. As such, I'd also probably declare the types as ConcurrentHashMap to make things a little safer (although there are still some dangerous operations such as sharing an Iterator between threads)

Question about Threads and Locks

Right now i am trying to learn more about java threading, and i have a small question that i cannot find a direct answer to anywhere. Lets say i have two threadsthat both share an object:
public class FooA implements Runnable
{
Object data;
public FooA(final Object newData)
{
data = newData;
}
public void doSomething()
{
synchronized(data)
{
data = new Integer(1);
}
}
public void run() {
// Does stuff
}
}
public class FooB implements Runnable
{
Object data;
public FooB(final Object newData)
{
data = newData;
}
public void doSomething()
{
synchronized(data)
{
System.out.println(data);
}
}
}
Would FooA block FooB when it is in the doSomething section of the code? Or vice versa? My gut feeling says yes, but according to the book i am reading it says no. Hence the need for monitor objects. I made a slightly more complex version of this, and everything worked fine.
I looked around a bit, but couldn't find a concrete answer.
There are a few issues with this example.
Firstly, synchronized(data) means that it synchronizes on the object that is in data at the time. If you've initialized your two objects with the same object, you should get the synchronization.
However, since you're setting data itself within the code, this won't really work after that (since it won't be the same object then).
final in the constructor's parameter isn't particularly useful. It would be more useful as a modifier on the field itself. It wouldn't work in this particular example because you're modifying the value, but in general, it's a good way of preventing some concurrency issues when you know the value is going to be fixed.
I made a slightly more complex version
of this, and everything worked fine.
It's very hard, or almost impossible, to debug concurrency issues by trial and error. The fact that it doesn't fail doesn't mean it will work reliably.
I'd recommend reading this book: http://www.javaconcurrencyinpractice.com/
The problem is that one of the synchronised blocks assigns a new object to data. If that block starts first, and changes data, subsequent runs will be using a different object to lock on. So from then on, both will be able to run simultaneously.
The answer is yes in this case but it is brittle (i.e. the next change to the code will probably break something). Why does it work?
Because FooB never notices that FooA changes the object (each thread gets its own reference, so FooB never notices when FooA assigns its reference a new value).
For cases like that, I suggest to use AtomicReference which makes sure that two threads can access the same object and anyone can update that reference any time and the other threads get the new value only after the update.
Any Java Object may be used for synchronization.
If FooA and FooB are both constructed with references to same object then they are sharing the same "lock" object and will block as you are expecting. As the
Object data;
decalrations are not final, either FooA or FooB, or both could assign different values to data, and then be synchronizing on different objects - which may be good or bad depending upon what you are trying to do.
In your code sample, fooA.data and fooB.data are not the same object unless someone initializes them as such with something like:
Object o = new Object();
FooA fooA = new FooA(o);
FooB fooB = new FooB(o);
Unless they are initialized to the same instance, they are not the same object, only the same type and name.
When FooA assigns new Integer(1) to data, they will again not be the same object, only the same type and name. So after that, they won't be synchronized unless you call:
fooB.data = fooA.data;
This would have to happen inside the synchronization block to guarantee synchronized execution.
Also,something to know about threading is that even if everything works once, that doesn't mean your program is correct or that it will work every time. Threading problems only occur when the timing happens to work out just right (or just wrong, as it were).
It's correct as far as you have to synchronize on the same object, but since one thread modifies the object referenced by "data", you would need to synchronize on "this".

What object should I lock on when I am passing a Collection<Foo> into a separate class?

Please refer to UML
The Connection class's constructor initializes its foos member via
foos = Collections.synchronizedList( new ArrayList<Foo>(10) );
When Connection#start() is invoked, it creates an instance of Poller (while passing the foos reference into Poller's constructor) & Poller is started (Poller is a Runnable).
Question: The Poller thread will add to & remove objects from the list based on external events. Periodically clients will invoke Connection#snapshot() to retrieve the list. Since the implementation within Poller will perform a check to avoid duplicates during additions, it is not thread safe.
e.g. implemention of Poller#run
if( _foos.indexOf( newFoo ) == -1 )
{
_foos.add( newFoo );
}
What can I synchronize on in Connection as well as Poller to order to be thread safe?
I'd take a look at CopyOnWriteArrayList as a replacement for the ArrayList in the example above. That way you won't need to synchronize on anything since you have a thread safe collection out of the box, so to speak...
http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/CopyOnWriteArrayList.html
From the API CopyOnWriteArrayList is...
A thread-safe variant of ArrayList in
which all mutative operations (add,
set, and so on) are implemented by
making a fresh copy of the underlying
array.
n.b. This is only a viable solution if the number of traversals outweigh the number of additions/updates to the collection. Is this the case?
There is a clean solution using interfaces and anonymous inner classes.
In the Connection class add the following:
public static interface FooWorker {
void onFoos(List<Foo> list);
}
public synchronized void withFoosSafely(FooWorker worker) {
worker.onFoos(foos);
}
In the Poller class do the following:
public void doWork() {
connection.withFoosSafely(new FooWorker() {
public void onFoos(List<Foo> list) {
/// add, remove and change the list as you see fit
/// everything inside this method is thread-safe
}
});
}
It requires a bit of additional code (no closures yet in Java) but it guarantees thread safety and also makes sure clients don't need to take care of locking - less potential bugs in the future.
You might return a new List from snapshot():
public List<Foo> snapshot() {
return new ArrayList<Foo>(foos);
}
Given that you're returning a "snapshot", it seems OK to me that the list is guaranteed to be up-to-date only at the moment it gets returned.
If you're expecting clients to add/remove members from foos, then you'd probably need to expose those operations as methods on Connection.
Perhaps I am not getting the point, it seems Connection#snapshot should be synchronized on this (or on _foos) and so does the code block of Poller that manages Connection._foos.
What am I missing?

Categories