Synchronized keyword- how it works? - java

If I have a class, call it X and X contains a collection (assume I am not using one of the synchronized colections, just a normal one).
If I was to write my own method synchronized add()- how does the locking work? Is the locking done on the instance of X, and not on the collection object?
So synchronizing my add() method would not stop many instances of X from calling add() and inserting into the collection- therefore I could still have threading problems?

A synchronized method locks the object. If your X.add is synchronized, it will prevent concurrent execution of other synchronized methods of the same X object. If anyone out of that X object has access to the same collection, the collection will not be protected.
If you want your collection to be protected, make sure it is not accessible to the rest of the world in any way other than a synchronized method of X. Also, this is a bit unclear in your question, but note that a synchronized non-static method locks the object. Assuming each X instance will have a collection of its own, they won't interfere with each other.
Another option, BTW, is to lock the collection instead of the X object:
void add(Object o) {
synchronized(myCollection) {
myCollection.add(o);
}
}
This will synchronize access to the locked collection instead of the X object. Use whichever you find easier and more effective.

In your example, synchronized will make sure only one thread can invoke the method on one instance of the class at a time. Other methods could access that collection, which would not be safe. Look up concurrent collections for more information on thread-safe collection implementations.

If I was to write my own method synchronized add()- how does the locking work? Is the locking done on the instance of X, and not on the collection object?
The locking is done on the object that you synchronized on -- not any fields within the object. For locking to work, all of the threads must synchronize on the same exact object. Typically a private final object is best to be locked on.
private final Collection<...> myCollection = ...
...
synchronize (myCollection) {
myCollection.add(...);
}
Although a common pattern is to lock on the object that you are protecting, it really can be any constant object. You could also do:
private final Object lockObject = new Object();
...
synchronize (lockObject) {
myCollection.add(...);
}
So synchronizing my add() method would not stop many instances of X from calling add() and inserting into the collection- therefore I could still have threading problems?
If other parts of your application are accessing the myCollection without being inside of a synchronized (myCollection) block, then yes, you are going to have threading problems. You would need to synchronize around all accesses to properly protect the collection and provide a memory barrier. That means add(...), contains(...), iterators, etc..
Often, if you are trying to protect a collection or other class, it makes sense to wrap it in a class which does the synchronization. This hides the locking and protects the collection from unintended modifications from code that is missing a synchronized block.

Is it true that you are sharing one collection across many X instances? Then you need to synchronize on the collection instance itself. Don't make the method itself synchronized, but wrap all its code in a synchronized(coll) { ... } block.
If, on the other hand, each X has its own collection, then synchronized add() is all you need. This will guarantee that no two threads are executing add on the same instance at the same time.

Related

Are Mutable Atomic References a Bad Idea?

I have a data structure that I occasionally wish to modify, and occasionally wish to replace outright. At the moment, I'm storing this in an AtomicReference, and using synchrnonized blocks (synchronized on the AtomicReference itself, not its stored value) when I need to modify it, rather than replace it.
So something like:
public void foo(AtomicReference reference){
synchronized(reference){
reference.get()
.performSomeModification();
}
}
Notice that the modifying call is a member of the wrapped value, not the atomic reference, and is not guaranteed to have any thread safety of its own.
Is this safe? Findbugs (a freeware code reviewing tool) had this to say about it, so now I'm worried there's something happening under the hood, where it may be prematurely releasing the lock or something. I've also seen documentation referencing AtomicReference as specifically for immutable things.
Is this safe? If it isn't I could create my own Reference-storing class that I would be more certain about the behavior of, but I don't want to jump to conclusions.
From the linked documentation:
For example, synchronizing on an AtomicBoolean will not prevent other threads from modifying the AtomicBoolean.
It can't prevent other threads from modifying the AtomicBoolean because it can't force other threads to synchronize on the AtomicBoolean.
If I understand your question correctly, your intention is to synchronize calls to performSomeModification(). The code you've written will achieve that, if and only if every call to performSomeModification() is synchronized on the same object. As in the example from the docs, the basic problem is the enforceability of that requirement. You can't force other callers to synchronize on the AtomicReference. You or some other developer who comes after you could easily call performSomeModification() without external synchronization.
You should make it hard to use your API incorrectly. Since AtomicReference is a generic type (AtomicReference<V>), you can enforce the synchronization in a variety of ways, depending on what V is:
If V is an interface, you could easily wrap the instance in a synchronized wrapper.
If V is a class that you can modify, you could synchronize performSomeModification(), or create a subclass in which it is synchronized. (Possibly an anonymous subclass produced by a factory method.)
If V is a class that you cannot modify, it may be difficult to wrap. In that case, you could encapsulate the AtomicReference in a class that you do control, and have that class perform the required synchronization.
Are Mutable Atomic References a Bad Idea?
Definitely not! AtomicReference is designed to provide thread-safe, atomic updates of the underlying reference. In fact, the Javadoc description of AtomicReference is:
An object reference that may be updated atomically.
So they most definitely are designed to be mutated!
Is this safe?
It depends on what you mean by "safe", and what the rest of your code is doing. There's nothing inherently unsafe about your snippet of code in isolation. It's perfectly valid, though perhaps a bit unusual, to synchronize on an AtomicReference. As a developer unfamiliar with this code, I would see the synchronization on reference and assume that it means that the underlying object may be replaced at any time, and you want to make sure your code is always operating on the "newest" reference.
The standard best practices for synchronization apply, and violating them could result in unsafe behavior. For example, since you say performSomeModification() is not thread-safe, it would be unsafe if you accessed the underlying object somewhere else without synchronizing on reference.
public void bar(AtomicReference reference) {
// no synchronization: performSomeModification could be called on the object
// at the same time another thread is executing foo()
reference.get().performSomeModification();
}
If could also be "unsafe" if your application requires that only one instance of the underlying object be operated on at any one time, and you haven't synchronized on the reference when .set()ing it:
public void makeNewFoo(AtomicReference reference) {
// no synchronication on "reference", so it may be updated by another thread
// while foo() is executing performSomeModification() on the "old" reference
SomeObject foo = new SomeObject();
reference.set(foo);
}
If you need to synchronize on the AtomicReference, do so, it's perfectly safe. But I would highly recommend adding a few code comments about why you're doing it.

When I call a method not synchronized from a synchronized what appen?

if I have two thread A and B that use the same class C.java what happens if thread A use a synchronized method(synchro()) that access use another class method(myMethod()) and after 1ms or minus thread B try to use myMethod()? He will wait until thread A has finished or it accesses to myMethod()? Thread A and Thread B use the same class instance.
Synchronization is not implicitly transitive. It is merely a lock on the object to execute a block of code. It does not lock the objects that are used inside the code block.
Thread B will have access to the unsynchronized method. Since it's not synchronized, Thread B doesn't need to wait to acquire an object monitor.
Implicit mutex lock will be introduced only for method synchro(), but not for myMethod(), since myMethod() is not synchronized. As a consequence access to myMethod() will not be syncronized between multiple threads.
It will access it.
Only synchronized methods or synchronized blocks cannot be executed concurrently: Synchronized Methods
There is no such thing as a synchronized method.
Repeat after me: There is no such thing as a synchronized method.
When you write this:
synchronized Foobar myFunk() { ... }
That's just syntactic sugar that saves you from having to write this instead:
Foobar myFunk() {
synchronized(this) { ... }
}
But the second one makes it more obvious what is really going on: It's not the method that is synchronized, it's the object.
The JVM will not allow two different threads to synchronize the same object at the same time. That's all it means. Synchronizing an object does not "lock" the object (other threads can still modify it). Synchronizing an object does not prevent other threads from calling the same method. All it does is prevent other threads from synchronizing the same object at the same time.
How you use that feature is up to you.
Normally, you use it to protect invariants. An invariant is an assertion that you make about some value or some group of values. (e.g., the length of list L is always even). If one thread must temporarily break the invariant (e.g., by first adding one thing to the list, and then adding another), and some other thread will crash and burn if it sees the broken invariant; then you need synchronization.
The first thread only breaks the invariant while inside a synchronized block, and any other thread only looks at the data when it is synchronized on the same object. That way, the one the looks can never see the invariant in the broken state.

What's synchronizes in Java Collection?

I'm trying to figure out what are synchronized on the Java collection framework. But still haven’t got any clear solution.
I mean, if we get
list
Queie
Set
And on the list
ArrayList
LinkedList
Vector
What are the synchronized?
If we get HashMap and HashTable we know Hashtable is synchronized on the table while access to the HashMap isn't.
Take a look on the following utility methods:
Collections.synchronizedCollection()
Collections.synchronizedList()
Collections.synchronizedSet()
Collections.synchronizedMap()
Not a single implementation of the collection is synchronized because synchronized is not a class property, it is only applicable to methods and blocks.
Each class in the jdk collection api documents whether it is thread safe or not. Older classes like java.util.Vector tended to be synchronized on every method, until they became replaced with a non synchronized version. ArrayList in this case. Then the concurrent package was added, and everything in there had a thread safety strategy of one kind or another. In general though, if the class documentation does not say that the class is thread safe then treat it as not being thread safe.
When you write
private Object syncObject = new Object();
public void someFunction(Stuff stuff)
{
synchronized(syncObject)
{
list.add(stuff);
}
}
public void someOtherFunction()
{
synchronized(syncObject)
{
for(Stuff stuff : list)
{
stuff.doStuff();
}
}
}
Then what it means is that the Monitor of the syncObject object does not allow multiple threads inside it, it allows only a single Thread into that object's monitor. This is called mutual exclusion, http://en.wikipedia.org/wiki/Mutual_exclusion
This is basically so that if you have multiple threads, then you can make execute specific code blocks only one thread at a time. For example, while you iterate the array through one, but you're adding items to that array in another, and you're removing in a third. You don't want them to mess with each other, because that can create inconsistent results.
The function
Collections.synchronizedCollection(Collection<T> c)
creates a Decorator around the Collection to make its methods synchronized, for example.
"Synchronized" means the methods of that class are synchronized. All the legacy classes(e.g. Vector, Hashtable, Stack) are considered to be synchronized. More specifically, the personal methods of these legacy classes are synchronized.
But now take an example of Vector class, Vector implements Collection interface hence it contains some utility methods from Collection interface(e.g. add(), remove() etc.), and these methods are not synchronized.
all legacy classes are the synchronize classes it means thread safe classes.
Vector and Stack are the synchronize and Enumeration is used to access the values in synchronize class.
Legacy classes are synchronized like Vector, Stack, HashMap. You also can check if all the methods of a particular class are synchronized or not like
javap java.util.HashMap
Which is not synchronized class
javap java.util.Hashtable
Which is synchronized as all the methods are synchronized of Hashtable

Java synchronized - am I doing it right?

I'm not used to working with synchronized. Does the following snippet look right?
public void setNewSessionListener(NewSessionListener newSessionListener) {
if (this.newSessionListener != null)
synchronized (this.newSessionListener) {
this.newSessionListener = newSessionListener;
}
else
this.newSessionListener = newSessionListener;
}
More specifically do I need to perform a null check? I have a gut feeling there is something fundamentally wrong with that code.
There are two mistakes. The first one is that if you access a field which requires synchronization, you always have to access it with the same lock held. Also you have to check if the field is null and write to the field in the same sychronized block, because otherwise when you write something to the field, it may already be not null.
The second one is that it is best to sychronize on something that doesn't change, in other words, on a static final field or on the instance itself. For example, you can create a lock object specifically for this purpose:
private static final Object LOCK = new Object();
And then you will write:
synchronized (LOCK) {
if (this.newSessionListener == null) this.newSessionListener = newSessionListener;
}
Your feeling is right. You should do the null check inside the synchronized block. Otherwise the block won't prevent double initialization. Furthermore, you shouldn't synchronize on this.newSessionListener which you are about to change - choose an object (reference) which is going to stay around for the whole scope of the block. This is the only way to guarantee that only one thread can enter this block of code at any point in time. The typical way to achieve this is to synchronize on this. Alternatively, you may synchronize on a private final object, kept for this sole purpose.
Moreover, ultimately you are performing the same assignment in both the if and the else branches, which is probably not what you want.
This is, at a minimum, a very bad idea. You are synchronizing on an object you then assign to.
Because you are using synchronized I assume this is called asynchronously and it could be called by one thread while another thread is inside this code. If so, you are not locking on a common object, you are locking on the value it is holding at that point in time.
Probably, and I stress probably, you can do synchronized (this). That will insure that all calls to this method for this specific object are synchronized. And that calls to other instances of this class are locked for that other object - but not across instances.
If you want to synchronize across all instantiated objects, call synchronized (YourClass)
Here's another possibility (i tend to prefer explicit locks over the synchronized block):
private ReentrantLock lock = new ReentrantLock();
lock.lock();
try {
// do your synchronized code here.
}
finally {
lock.unlock();
}
Though just by looking at your code, i'm not sure why there's even an if block. Why are you synchronized in one case, and not the other? Especially considering you're making the same assignment in either case?

Synchronized threads and locking

Can someone please explain the difference between these two examples in the context of object locking:
public void method1(){
synchronized(this){
....
}
}
And
StringBuffer aStringBufferObject = new StringBuffer("A");
public void method2(){
synchronized(aStringBufferObject){
....
}
}
I know the first example will obtain a lock on the this instance and the second will obtain a lock of the aStringBufferObject instance. But i dont really understand what the effect or the difference of the two is.
For example, in the second example, will threads still be able to execute the code inside the synchronized block because the lock is not related to the 'this' instance?
I know that synchronizing a method or a block of code prevents multiple threads to access that block/method at the same time but what is the purpose of specifying the object to lock on and what is the difference in the way the object is specified as in the above examples?
What is the purpose of specifying the object to lock on?
Often, it is easier to synchronize on this or on the Class instance (for static methods). But, there are cases where you will need to synchronize on a specific object instead of the implicit lock (this). Such cases include:
You want to synchronize access to primitives without using this. You can only synchronize on Objects as each Object is associated with an implicit monitor in Java. Primitives do not have such implicit monitors, and therefore you need to use a lock object. Using the wrapper classes are a poor and incorrect choice, especially if you end up modifying the lock object in the guarded block.
You want to synchronize on an object that actually protects the critical section, when synchronizing on this would not offer a guarantee of thread safety. For instance, if you are synchronizing access to a ArrayList instance shared across instances of class A, then synchronizing on an instance of A is useless. A thread might create a new instance of A and gain access to the list, while another thread is modifying it. If you use a different lock that all threads must contend for then you can protect the list; this lock could be the one associated with A.class, but it could be any object that will offer the same guarantees.
You want to perform lock splitting to ensure that different guarded blocks are protected by different locks instead of the same lock. In other words, if it is thread-safe to allow different threads to acquire different locks to access different critical sections, then you can have a different lock for every critical section.
The following is an example of split lock usage:
private Object method1Lock = new Object();
private Object method2Lock = new Object();
public void method1(){
synchronized(method1Lock){
....
}
}
public void method2(){
synchronized(method2Lock){
....
}
}
You would use split locks when you can ensure that the concurrent execution of method1 and method2 do not violate the class invariants. This way, you can improve performance across threads that need access to the same object, but will be invoking different methods.
On your other question,
For example, in the second example, will threads still be able to execute the code inside the synchronized block because the lock is not related to the 'this' instance?
In the second example, any thread entering the guarded region must acquire the lock associated with aStringBufferObject. If a different thread is holding that lock, then the current thread will not proceed further. When you specify this, then the thread must acquire the lock associated with the current object. In both cases, a thread must acquire a lock; the examples are only different in the object that is being used as a lock.
Synchronizing on an object means that other blocks which synchronize on the same object will have to wait. For example:
public void methodA() {
synchronized(obj) {
//Do one job
}
}
public void methodB() {
synchronized(obj) {
//Do another job
}
}
If you call methodA() in one thread and then call methodB() in another thread, methodB() won't finish before methodA() finishes.
The synchronized block is a monitor, which leave out of details to lock and unlock a mutex. Because every object in Java has an internal lock(refer to source code of Object class), when use synchronized statement, the JVM will help you synchronize the critical section. You can also synchronize block yourself use ReentrantLock in package java.util.concurrent.locks.

Categories

Resources