Java method vs member synchronization - java

I know that java's synchronization primitive, when applied to a method, is the semantic equivalent of taking a lock out on the object itself for the duration of the method's execution.
However, I'm unclear on this primitive's contract w.r.t. methods that access specific members of the object concurrently. Is the contract that this primitive only protects concurrent access across other members that also use it, or across any member that synchronizes on any underlying member of this object?
For instance, If foo() and bar() in the example below are invoked concurrently, can this lead to data races on innerThing?
class Thing {
InnerThing innerThing;
OtherInnerThing otherInnerThing;
public synchronized void foo() {
innerThing.mutate();
}
public void bar() {
synchronized(innerThing) {
innerThing.mutate();
}
}
}

Is the contract that this primitive only protects
concurrent access across other members that also
use it, or across any member that synchronizes on
any underlying member of this object.
The former. All threads must synchronize on the same object.
If thread 1 is sync'd on the instance, and thread 2 attempts to sync on some member object of that instance, thread 2 will not be blocked.
This is implicit in the Java Language Specification; the wording talks about 'the same monitor'.

Related

If a method is synchronized, do the called methods also have to be synchronized?

If a method is synchronized, do the called methods also have to be synchronized? What is correct in the following example?
// Only parent method synchronized
public synchronized void parentMethod() {
childMethod1();
}
public void childMethod1() {
childMethod2();
}
public void childMethod2() {
}
// All methods synchronized
public synchronized void parentMethod() {
childMethod1();
}
public synchronized void childMethod1() {
childMethod2();
}
public synchronized void childMethod2() {
}
If a method is synchronized, do the called methods also have to be synchronized?
No.
There is no general reason that you need to call a synchronized method from another synchronized method.
Assuming that the methods are synchronizing on the same object then all patterns are valid, depending on what you are trying to achieve:
calling a synchronized method from a synchronized method
calling a synchronized method from a plain method
calling a plain method from a synchronized method
calling a plain method from a plain method
In all but the last case, the called method will hold the lock on the target object.
(In the first case, it appears as if the thread is going to the same object twice. In fact, Java primitive locks are re-entrant ... so this is not a problem.)
If the method calls were on different target objects, it gets a bit more complicated. Now you have to consider whether your application requires both objects to be locked. Also you need to consider the possibility of deadlocks. (If two threads attempt to simultaneously acquire the same two primitive locks, but in a different order, you will get a deadlock.)
It is not actually possible to give hard rules about which methods need to be synchronized1. It depends on what the methods do, and whether you are using primitive lock mutexes or some other mechanism (Lock, volatile, immutable types, etc) to synchronize and/or ensure memory visibility. And even for primitive lock mutexes, you can either use synchronized methods of synchronized blocks to achieve the same thing.
1 - Note that the question doesn't ask this anyway!

How to avoid creating Thread hostile classes in Java

In effective java 2nd Edition Item 70 Josh Bloch explained about thread hostile classes
This class is not safe for concurrent use even if all method
invocations are surrounded by external synchronization. Thread
hostility usually results from modifying static data without
synchronization
Can Someone explain me with example how it's impossible to achieve thread safety by external synchronization if the class modifies shared static data without internal synchronization?
The citation assumes the synchronization of every call to the class method on the same object instance. For example, consider the following class:
public class Test {
private Set<String> set = new TreeSet<>();
public void add(String s) {
set.add(s);
}
}
While it's not thread-safe, you can safely call the add method this way:
public void safeAdd(Test t, String s) {
synchronized(t) {
t.add(s);
}
}
If safeAdd is called from multiple threads with the same t, they will be mutually exclusive. If the different t is used, it's also fine as independent objects are updated.
However consider that we declare the set as static:
private static Set<String> set = new TreeSet<>();
This way even different Test objects access the shared collection. So in this case the synchronization on Test instances will not help as the same set may still be modified concurrently from different Test instances which may result in data loss, random exception, infinite loop or whatever. So such class would be thread-hostile.
Can Someone explain me with example how it's impossible to achieve thread safety by external synchronization if the class modifies shared static data without internal synchronization?
It's not impossible. If the class has methods that access global (i.e., static) data, then you can achieve thread-safety by synchronizing on a global lock.
But forcing the caller to synchronize threads on one global lock still is thread-hostile. A big global lock can be a serious bottleneck in a multi-threaded application. What the author wants you to do is design your class so that it would be sufficient for the client to use a separate lock for each instance of the class.
Perhaps a contrived example, but this class is impossible to synchronize externally, because the value is accessible from outside the class:
public class Example {
public static int value;
public void setValue(int newValue) {
this.value = newValue;
}
}
However you synchronize invocation of the setter, you can't guarantee that some other thread isn't changing value.

Instance methods and thread-safety of instance variables

I would like to known if each instance of a class has its own copy of the methods in that class?
Lets say, I have following class MyClass:
public MyClass {
private String s1;
private String s2;
private String method1(String s1){
...
}
private String method2(String s2){
...
}
}
So if two differents users make an instance of MyClass like:
MyClass instanceOfUser1 = new MyClass();
MyClass instanceOfUser2 = new MyClass();
Does know each user have in his thread a copy of the methods of MyClass? If yes, the instance variables are then thread-safe, as long as only the instance methods manipulate them, right?
I am asking this question because I often read that instance variables are not thread-safe. And I can not see why it should be like that, when each user gets an instance by calling the new operator?
Each object gets its own copy of the class's instance variables - it's static variables that are shared between all instances of a class. The reason that instance variables are not necessarily thread-safe is that they might be simultaneously modified by multiple threads calling unsynchronized instance methods.
class Example {
private int instanceVariable = 0;
public void increment() {
instanceVariable++;
}
}
Now if two different threads call increment at the same then you've got a data race - instanceVariable might increment by 1 or 2 at the end of the two methods returning. You could eliminate this data race by adding the synchronized keyword to increment, or using an AtomicInteger instead of an int, etc, but the point is that just because each object gets its own copy of the class's instance variables does not necessarily mean that the variables are accessed in a thread-safe manner - this depends on the class's methods. (The exception is final immutable variables, which can't be accessed in a thread-unsafe manner, short of something goofy like a serialization hack.)
Issues with multi-threading arise primarily with static variables and instances of a class being accessed at the same time.
You shouldn't worry about methods in the class but more about the fields (meaning scoped at the class level). If multiple references to an instance of a class exist, different execution paths may attempt to access the instance at the same time, causing unintended consequences such as race conditions.
A class is basically a blueprint for making an instance of an object. When the object is instantiated it receives a spot in memory that is accessed by a reference. If more than one thread has a handle to this reference it can cause occurrences where the instance is accessed simultaneously, this will cause fields to be manipulated by both threads.
'Instance Variables are not thread safe' - this statement depends on the context.
It is true, if for example you are talking about Servlets. It is because, Servlets create only one instance and multiple threads access it. So in that case Instance Variables are not thread safe.
In the above simplified case, if you are creating new instance for each thread, then your instance variables are thread safe.
Hope this answers your question
A method is nothing but a set of instructions. Whichever thread calls the method, get a copy of those instructions. After that the execution begins. The method may use local variables which are method and thread-scoped, or it may use shared resources, like static resources, shared objects or other resources, which are visible across threads.
Each instance has its own set of instance variables. How would you detect whether every instance had a distinct "copy" of the methods? Wouldn't the difference be visible only by examining the state of the instance variables?
In fact, no, there is only one copy of the method, meaning the set of instructions executed when the method is invoked. But, when executing, an instance method can refer to the instance on which it's being invoked with the reserved identifier this. The this identifier refers to the current instance. If you don't qualify an instance variable (or method) with something else, this is implied.
For example,
final class Example {
private boolean flag;
public void setFlag(boolean value) {
this.flag = value;
}
public void setAnotherFlag(Example friend) {
friend.flag = this.flag;
}
}
There's only one copy of the bytes that make up the VM instructions for the setFlag() and setAnotherFlag() methods. But when they are invoked, this is set to the instance upon which the invocation occurred. Because this is implied for an unqualified variable, you could delete all the references to this in the example, and it would still function exactly the same.
However, if a variable is qualified, like friend.flag above, the variables of another instance can be referenced. This is how you can get into trouble in a multi-threaded program. But, as long as an object doesn't "escape" from one thread to be visible to others, there's nothing to worry about.
There are many situations in which an instance may be accessible from multiple classes. For example, if your instance is a static variable in another class, then all threads would share that instance, and you can get into big trouble that way. That's just the first way that pops into my mind...

What is the difference between synchronized(this) and synchronized(ClassName.class)?

I read somewhere that synchronized(this) should be avoided for various reasons. Yet some respectable code that I encountered uses the following in the constructor:
public SomeClass(Context context) {
if (double_checked_lock == null) {
synchronized (SomeClass.class) {
if (double_checked_lock == null) {
// some code here
}
}
}
}
Is there really a difference between synchronized(this) and synchronized(SomeClass.class)?
synchronized(this) is synchronized on the current object, so only one thread can access each instance, but different threads can access different instances. E.g. you can have one instance per thread.
This is typically useful to prevent multiple threads from updating an object at the same time, which could create inconsistent state.
synchronized(SomeClass.class) is synchronized on the class of the current object ( or another class if one wished) so only one thread at a time can access any instances of that class.
This might be used to protect data that is shared across all instances of a class (an instance cache, or a counter of the total number of instances, perhaps) from getting into an inconsistent state .
this is different for each instance.
ClassName.class is not.
Therefore, synchronized(this) will allow multiple instance to run simultaneously.
The synchronized keyword, when applied to a class locks on the class, and when it's applied to this locks on the current object instance. From the Java Language Specification, section 8.4.3.6, 'synchronized Methods':
A synchronized method acquires a monitor (ยง17.1) before it executes. For a class (static) method, the monitor associated with the Class object for the method's class is used. For an instance method, the monitor associated with this (the object for which the method was invoked) is used.
Each java Object can have a lock. This lock can be held by at most one thread at a time, any other thread has to wait to get the lock of the same object.
synchronized(this) acquires the lock of the instance this for the current thread. The method can run parallel on different instances (different values for this and therefore different locks)
synchronized(SomeClass.class) acquires the lock of the global class object of SomeClass. Only one instance of the method can run as all object instances lock on the same global object (same lock).
These are 2 different object to lock on:
'this' refer to current instance context, so creating multiple instances will have no effect if, for example, each thread using a different instance and lock on it. 'this' can be referred only on non-static context.
the 'class' is a static member of the Java Class and there is exactly one instance of it. You can lock on it in both static and non-static context.
synchronized(this) synchronizes on the instance of the object.
synchronized(SomeClass.class)uses the instance of the Class object that represents SomeClass, which is global for all instances in the same classloader.
Thus, these are different constructs with different semantics.
Using synchronized alone, or as a method modifier, also synchronizes on the instance's semaphore, which is normally used to prevent contention between multiple threads accessing that instance as a shared resource (i.e. a List).
The thread you refer states that it's a better practice to use a private instance, as synchronizing directly on your object instance may be dangerous. For that you'd use:
class MySharedResourceClass {
private SomeClass lock = new SomeClass();
public doSomething() {
synchronized (lock) {
// Do something here
}
}
}

Java: A synchronized method in the superclass acquires the same lock as one in the subclass, right?

class A {
public synchronized void myOneMethod() {
// ...
}
}
class B extends A {
public synchronized void myOtherMethod() {
// ...
}
}
// ...
B myObject;
// ...
myObject.myOneMethod(); // acquires lock
myObject.myOtherMethod(); // same lock?
How I understand the synchronization model, I'd say that yes, it does, because the lock / monitor is associated with the instance myObject, and it doesn't matter where the method was defined. But am I right? If not, why? If yes, why are you sure, and I'm not? :-)
Yes, you are right, and you got the explanation right too. Nothing much to add.
Note that if the methods were static, then they would synchronize on different objects, namely their respective classes (A and B).
EDIT: Why am I sure? I don't know, why are you not sure? ;-) myObject is just one object - there isn't any distinction between the myObject attributes that come from class A and those that come from class B. (Well, technically you could probably use reflection to find out which are which, so there must be some distinction, but forget about reflection for now. For common operations on the object there's no distinction.)
Yes, synchronized is equivalent to synchronized(this).
To be more precise:
For a class (static) method, the lock associated with the Class object for the method's class is used. For an instance method, the lock associated with this (the object for which the method was invoked) is used.
If you want to be more explicit about your locking, you could do something like this:
class A {
protected final Object mutex = new Object();
public void myOneMethod() {
synchronized (mutex) {
// ...
}
}
}
class B extends A {
public void myOtherMethod() {
synchronized (mutex) {
// ...
}
}
}
In fact, this pattern is recommended by Brian Goetz in Java Concurrency in Practice, section 4.2.1 "The Java monitor pattern". That way you know exactly where your monitor is coming from.
Yes. Java uses "monitors" to implement synchronization, and synchronized methods use the object instance they're called on as monitor, which is obviously the same in this case.
Note that this is NOT true for static methods! There, the class instance of (I think) the declaring class is used, which would not be the same one.
Yes you are correct
When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object. In this case the object is B
Just a small addition for people who might be interested in the future..
Additionally remember that locks in Java are reentrant. If they were not this code of yours would result in a deadlock since as you've indicated both operations require the same lock.
From the conceptual viewpoint, the mutex integrity of some inheritance scenarios would be broken if synchonized methods of class A would only protect A's data in the context of subclass B. After all, not all of A's data is required to be private.
Imagine that you want to slightly extend the functionality of one method of A while keeping the rest of A's functionality including mutex protection. If A were only protecting itself, you would end up having to override all of A's synchronized methods to lift the original synchronization mechanism to the new subclass. Not very attractive and also not very efficient.

Categories

Resources