Java Static Synchronized [duplicate] - java

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How do synchronized static methods work in Java?
Can someone make me understand the fundamental difference between the following two functions:
public static void synchronized f() {… }
and
public void synchronized f() {… }

In the case of
public void synchronized f(){...}
The synchronization is per instance of the of enclosing class. This means that multiple threads can call f on different instances of the class.
For
public static void synchronized f(){...}
Only one thread at a time can call that method, regardless of the number of instances of the enclosing class.
Technically, the monitor taken by synchronized in the first example is the of the object instance and the monitor take in the second example is that of the Class object.
Note that, if you have classes of the same name in different ClassLoaders, the do not share the same monitor, but this is a detail you're unlikely to encounter.

In a "static synchnronized" method, the lock that is synchronized against is on the class itself; in a "synchornized" method, the lock is on the object. Note that this means that a "static synchronzied" method will not be blocked by a running "synchronzied" method, and vice versa. For more info, see: http://geekexplains.blogspot.com/2008/07/synchronization-of-static-and-instance.html

I think:
public void synchronized f() {… } synchronizes on object itself (this)
public static void synchronized f() {… } synchronizes on Class instance of an object (object.getClass() or SomeClass.getClass)
I can be wrong

Assuming the method f is in a class Foo. The static version will lock on the the static method call at the class level (the object returned by getClass() or Foo.class). The non static version will lock for particular instances of that class, so lets say:
Foo x = new Foo();
Foo y = new Foo();
// Locks method f of instance x, but NOT for y.
x.f();
In the static instance a call to f() will lock for both versions so only one method call to f would be executing at one time.

Related

Why is this class not thread safe?

class ThreadSafeClass extends Thread
{
private static int count = 0;
public synchronized static void increment()
{
count++;
}
public synchronized void decrement()
{
count--;
}
}
Can anyone explain why above class is not thread safe?
Since the increment method is static it will synchronize on the class object for the ThreadSafeClass. The decrement method is not static and will synchronize on the instance used to call it. I.e., they will synchronize on different objects and thus two different threads can execute the methods at the same time. Since the ++ and -- operations are not atomic the class is not thread safe.
Also, since count is static, modifying it from decrement which is a synchronized instance method is unsafe since it can be called on different instances and modify count concurrently that way.
You have two synchronized methods, but one of them is static and the other is not. When accessing a synchronized method, based on it's type (static or non-static), a different object will be locked. For a static method, a lock will be put on the Class object, while for the non-static block, a lock will be put on the instance of the class that runs the method. Because you have two different locked objects, you can have two threads that modify the same object simultaneously.
Can anyone explain why above class is not thread safe?
increment being static, synchronization will be done on the class itself.
decrement being not static, synchronization will be done on the object instantiation, but that doesn't secure anything as count is static.
I'd like to add that to declare a thread-safe counter, I believe the simplest way is to use AtomicInteger instead of a primitive int.
Let me redirect you to the java.util.concurrent.atomic package-info.
Others' answers are pretty good explained the reason. I just add something to summarize synchronized:
public class A {
public synchronized void fun1() {}
public synchronized void fun2() {}
public void fun3() {}
public static synchronized void fun4() {}
public static void fun5() {}
}
A a1 = new A();
synchronized on fun1 and fun2 is synchronized on instance object level. synchronized on fun4 is synchronized on class object level. Which means:
When 2 threads call a1.fun1() at same time, latter call will be blocked.
When thread 1 call a1.fun1() and thread 2 call a1.fun2() at same time, latter call will be blocked.
When thread 1 call a1.fun1() and thread 2 call a1.fun3() at same time, no blocking, the 2 methods will be executed at same time.
When thread 1 call A.fun4(), if other threads call A.fun4() or A.fun5() at same time, latter calls will be blocked since synchronized on fun4 is class level.
When thread 1 call A.fun4(), thread 2 call a1.fun1() at same time, no blocking, the 2 methods will be executed at same time.
decrement is locking on a different thing to increment so they do not prevent each other from running.
Calling decrement on one instance is locking on a different thing to calling decrement on another instance, but they are affecting the same thing.
The first means that overlapping calls to increment and decrement could result in a cancel-out (correct), an increment or a decrement.
The second means that two overlapping calls to decrement on different instances could result in a double decrement (correct) or a single decrement.
Since two different methods, one is instance level and other is class level, so you need to lock on 2 different objects to make it ThreadSafe
As explained in other answers, your code is not Thread safe since static method increment() locks Class monitor and non-static method decrement() locks Object monitor.
For this code example, better solution exists without synchronzed keyword usage.
You have to use AtomicInteger to achieve Thread safety.
Thread safe using AtomicInteger:
import java.util.concurrent.atomic.AtomicInteger;
class ThreadSafeClass extends Thread {
private static AtomicInteger count = new AtomicInteger(0);
public static void increment() {
count.incrementAndGet();
}
public static void decrement() {
count.decrementAndGet();
}
public static int value() {
return count.get();
}
}

java thread accessing outer object before it's created

Yes, this is an academic question, I know people will complain that I'm not posting any code
but I'm genuinely struck with this question, really don't know where to begin. I would really appreciate an explanation and maybe some code example.
If an object constructor starts a new thread that executes the method
run of an anonymous inner class object, it is possible that this new
thread can access its surrounding outer object before it has been
fully constructed and its fields fully initialized. How would you
prevent this from happening?
This is called "leaking this". Here you have the code
public class Test {
// this is guaranteed to be initialized after the constructor
private final int val;
public Test(int v) {
new Thread(new Runnable() {
#Override public void run() {
System.out.println("Val is " + val);
}
}).start();
this.val = v;
}
}
Guess what it will (may, since it's a thread) print. I used a final field to stress that the object is accessed before it has been fully initialized (final fields must be definitely assigned after the last line of every constructor)
How do you recover
You don't want to pass this around when you are in a constructor. This also mean you don't want to call non-final virtual methods in the very same class (non-static, non-private), and not using inner classes (anonymous classes are inner classes), that are implicitely linked to the enclosing instance, thus it's as they could access this.
Think about the single-threaded situation first:
Whenever you create an object via new, its constructor is called which (hopefully) initializes the fields of the new object before a reference to this object is returned. That is, from the point of view of the caller, this new is almost like an atomic operation:
Before calling new, there is no object. After returning from new, the object exists fully initialized.
So all is good.
The situation changes slightly when multiple threads come into play. But we have to read your quote carefully:
...has been fully constructed and its fields fully initialized.
The crucial point is fully. The subject line of your question says "before created", but what is meant here is not before the object has been created, but between object creation and initialization. In a multi-threaded situation, new can no longer be considered (pseudo-)atomic because of this (time flows from left to right):
Thread1 --> create object --> initialize object --> return from `new`
^
|
| (messing with the object)
Thread2 ------------------/
So how can Thread2 mess with the object? It would need a reference to that object but since new will only return the object after is both been created and initialized, this should be impossible, right?
Well, no - there is one way where it's still possible -- namely if Thread 2 is created inside the object's constructor. Then the situation would be like this:
Thread1 --> create object --> create Thread2 --> initialize object --> return from `new`
| ^
| |
| | (messing with the object)
\-----/
Since Thread2 is created after the object has been created (but before it has been fully initialized), there is already a reference to the object that Thread2 could get a hold of. One way is simply if the constructor of Thread2 explicitly takes a reference to the object as a parameter. Another way is by using a non-static inner class of the object for Thread2's run method.
I would change the title of the question, as threads are not accessing themselves, but the second one to the first one. I mean:
You have one thread, creating an object.
Inside the constructor for this object, you declare an anonymous inner class that implements Runnable.
In the same constructor of the first thread, you start a new thread to run your anonymous inner class.
Thus, you're having two threads. If you want to assure that the new thread doesn't do anything before the constructor is "fully ended", I would use some locks in the constructor. This way, the 2nd thread can be started but will wait until the first thread ends.
public class A {
int final number;
A() {
new Thread(
new Runnable() {
public void run() {
System.out.pritnln("Number: " + number);
}
}).start();
number = 2;
}
}
I do not fully agree with Pablos answer because it heavily depends on your initialization method.
public class ThreadQuestion {
public volatile int number = 0;
public static void main(String[] args) {
ThreadQuestion q = new ThreadQuestion();
}
public ThreadQuestion() {
Thread t = new Thread(new Runnable() {
#Override
public void run() {
System.out.println(number);
}
});
try {
Thread.sleep(500);
} catch(Exception e) {
e.printStackTrace();
}
number = 1;
t.start();
}
}
When you
place t.start() at the end, the correct data is printed.
place t.start() before the sleep command, it will print 0
remove the sleep command and place t.start() before the assignment it can print 1 (not determinable)
Play a mind game on 3.) you can say a "tiny" assignment of 1 simple data type will work as expected but if you create a database connection it will not achieve a reliable result.
Do not hesitate to raise any question.
So a situation like this?
public class MyClass {
private Object something;
public MyClass() {
new Thread() {
public void run() {
something = new Object();
}
}.start();
}
}
Depending on the actual code used, the behaviour could vary. This is why constructors should be carefully made so that they don't for example call non-private methods (a subclass could override it, allowing the superclass this to be accessed from a subclass before the superclass is fully initialized). Although this particular example deals with a single class and a thread, it's related to the reference leaking problem.

Making a class Thread-Safe

Given:
public class TestSeven extends Thread {
private static int x;
public synchronized void doThings() {
int current = x;
current++;
x = current;
}
public void run() {
doThings();
}
}
Which statement is true?
A. Compilation fails.
B. An exception is thrown at runtime.
C. Synchronizing the run() method would make the class thread-safe.
D. The data in variable "x" are protected from concurrent access problems.
E. Declaring the doThings() method as static would make the class thread-safe.
F. Wrapping the statements within doThings() in a synchronized(new Object()) { } block would make the class thread-safe.
isn't it enough to mark doThings() as synchronized in order to make that class Thread-safe ? i see that the correct answer is D but the Model answer of this question is E, But i don't understand why?
E. Declaring the doThings() method as static would make the class thread-safe.
That is kind of a tricky answer. The method is already synchronized, but on the instance, whereas the state is in a static field, i.e. on the class. Making it static synchronized is indeed the correct answer, because then it synchronizes on the class, not on a (meaningless) instance.
D. The data in variable "x" are protected from concurrent access problems.
private static int x;
This is a static variable. It is shared by all instances of the class, so synchronizing on individual instances is not helpful, in the same way as F would not be helpful, which synchronizes on a complete throw-away dummy object.
According to the language spec:
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.
This means that in the code you provided the synchronized keyword causes the method to acquire a lock on this before executing the body of the method. However, since x is static that doesn't ensure that the update to x will be atomic. (Another instance of the class could enter the synchronized region and do an update at the same time since they have different this values and thus different locks.)
However, declaring doStuff static will make all calls to the method acquire the same lock (the one on the Class) and thus would ensure mutual exclusion in the method body.
The specifications is really spelling out that:
class A {
static synchronized void doSomething() {
// ...
}
}
is literally the same thing as
class A {
static void doSomething() {
synchronized(A.class) {
// ...
}
}
}
Similarly:
class B {
synchronized void doSomething() {
// ...
}
}
is literally the same thing as
class B {
void doSomething() {
synchronized (this) {
// ...
}
}
}
By way of synchronizing the doThings() method, you are holding the lock for a particular TestSeven object. However, static variables of the class does not belong to the specific instance of the object itself. They belong to the Class object TestSeven.class. So, either you could go for a
synchronized (TestSeven.class){
int current = x;
current++;
x = current;
}
inside your doThings() method which is acquiring the Class lock inside an instance lock which is overdoing things. So, you could mark the method as static so that you end up acquiring the lock of the Class object alone.
Since x is static other threads could modify it at the same time doThings method is running. Making doThings static will stop this.
I agree with you that the correct answer is D.
I would say that E is incorrect because if I set doThings() as static and remove the synchronized keyword, I could just start up 50 TestSeven threads and it could result in incorrect x value.
Note:
I was wrong here, I missed the point that synchronized method without static actually use the instance as the lock monitor instead of the Class itself.

Static method access to a non static variable inside a thread

I have:
public class UTIL{
public static void met(){
do_something(){
print(A.m());
}
}
}
public class A{
public <type> m;
public <type>static m(){
return m;
}
}
Now:
Thread A contains instance of class A
Thread B contains instance of class A
From Thread B, at some point UTIL.met is called.
Question:
When UTIL.met is called, will it use m from the instance of A in Thread B?
When UTIL.met is called, will it use m from the instance of A in Thread B?
No, it doesn't matter if Thread A has one instance and Thread B has another. A.m is static and common for all instances.
But it is definitely the case that if the variables are static, then both threads will use the same variable.
(In other words, without proper synchronization, you'll have nasty race-conditions.)
m is a class variable, so is is actually common for all instances.
UTIL.met() will use the same instance of m that is "being held" [or can be accessed is a better terminology...] in all instances of A.
m is defined as a static variable in A. So it will common/shared among all instances of A.
If m is not static on the other hand, then of course each instance will have its own copy.
Well since thread A and thread B each contains own instance of class A, then each thread will use its instance of A.
is that what you want to achieve or you wanted to share m between instances??

Synchronzied Getter and Setter

I am studying Java concurrency right now. I have a question about synchronized and locks.
For any mutable data, we should put all the method accessing the data in the same lock.
But, what does same lock mean?
Example:
public class SynchronizedInteger{
private int value;
public synchronized int get(){return value;}
public synchronized void set(int value){this.value=value;}
}
So, my question is why this two methods are in the same lock? I know they are, but I would like to know why? And, does it mean that all the synchronized methods in the class are in the same lock?
Edit:
so, if I added one more method to the class:
public synchronized void printOneToHunder(){
for(int i=0;i<100;i++) System.out.println(i);
}
This method will also be included into same block as setter and getter? So, other thread cannot run this method when there is one thread using either setter or getter?
And, what if I change the class to below:
public class SynchronizedInteger{
private int value1;
private int value2;
public synchronized int get1(){return value1;}
public synchronized void set1(int value){this.value1=value1;}
public synchronized int get2(){return value2;}
public synchronized void set2(int value){this.value2=value2;}
}
For my understanding right now, only one thread can call these method at one time. So what's the way to make one thread can modify value1 and the other thread to modify value2???
Thanks a lot for your kindly clarifications!!!!
All non-static methods that you declare synchronized behave essentially as if the code was:
public synchronized int get() {
synchronized(this) {
// the method code
}
}
i.e. there is an implicit lock on this taken. So all non-static synchronized methods will lock the instance on which they are called.
Static synchronized methods take a lock on the class object itself, rather than an instance of that class.
Yes, your two methods are using the same lock.
The synchronized keyword without parameter is implicitly translated to syncrhonized(this), which is the same object for both methods.
In order for two blocks to have "the same lock" in java, it means that they are both using the same object as a lock. And as I said, in your case, both methods are using this as the lock object.
When you declare a method synchronized, it means that synchronization is on the particular instance for which the method is being invoked.
But you have other ways for synchronization.
Synchronized blocks:
synchronized(someLockedObj){somecode}
Lock-Objects:
Lock lock = new ReentrantLock(); lock.lock(); lock.unlock();

Categories

Resources