I have seen usage of synchronized block by this so far but recently I learned that using dummy object is preferable. I found the following topic related to this.
Java synchronized method lock on object, or method?
As a summary, in the code below, two different object can not run addA and addB concurrently as both uses this for lock.
private int a;
private int b;
public synchronized void addA(){
a++;
}
public synchronized void addB(){
b++;
}
I am confused if I use dummy object for lock, what will be different if I use the line below in both method to synchronize? Because still they would have same lock.
synchronized(dummyObject){
...
}
So what it means that I should have two different dummy object for each method to use with sycnhronized as?
public void addA(){
synchronized(dummyObj1){
a++;
}
}
public void addB(){
synchronized(dummyObj2){
b++;
}
}
That is exactly the point of lock objects - you can use different locks for different operations. Assuming it makes sense to run addA and addB concurrently (and from the looks of it - it definitely does), you should indeed have two separate locks, one for each method.
You are correct. In this case you need two different objects to synchronize on them separately.
For locking purpose the easiest way is to create Object objects.
Object lock1 = new Object();
Object lock2 = new Object();
Related
I have recently begun to understand how the Java Memory Model works (I don't fully yet).
I now understand that if I have non-final, non-volatile fields in my classes then it is possible for the value of those fields to not be immediately visible to other threads post construction e.g.
public class Example {
Object a;
Object b;
public Example() {
this.a = new Object();
this.b = new Object();
}
}
Example e = new Example();
// now imagine we are in another thread
e.a // could this in theory be null?
e.b // could this in theory be null?
What I'm not sure about is weather if I add a third volatile variable and set it at the end will the writes to a and b be guaranteed to be visible to other threads?
public class Example2 {
Object a;
Object b;
volatile Object c;
public Example2() {
this.a = new Object();
this.b = new Object();
this.c = new Object();
}
}
// some where else
Example2 e2 = new Example2();
// are e2.a and e2.b guaranteed to be visible to all other threads? I know (e2.c will be)
This is not something I particularly want to use but I want to understand what would happen in this case.
The constructor runs in a single thread and the instance is not "visible" to other threads until the constructor completes.
So, in this example, a and b will only be seen in other threads as null if they are subsequently set to null post-constructor.
The volatile keyword addresses possible optimizations in which a thread may continue to use an old value for a field after it changes on another thread due to local caching of the value. By adding volatile to the field, such optimizations are disabled.
By the way, if there's a need to synchronize across threads, using volatile fields is not ideal. Using atomic classes or other constructs from java.util.concurrent is advisable.
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();
}
}
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.
I want to get an object by a static factory method, such as
Person p = Person.fromName("Jack");
class Person {
public static Person fromName(String name){
return new Person(name);
}
}
but fromName() method is not thread safe, (fromName() is just an example, this kind of method will occur error when it's running in my program) however, it's inefficient if synchronized this method because multiple threads should call this method concurrently. Is there any suggestion to fix it?
If you've got code which is unsafe to execute in multiple threads concurrently, but you want to call it from multiple threads, it sounds like you really only have two options:
Make it thread-safe
Take the hit of serializing calls via synchronization
You haven't given any information which would suggest which of these is most appropriate in your situation. (Have you measured the performance hit of synchronization? Have you tried to make it thread-safe?)
Your problem seems unsolvable when you say that
A) the method is not thread safe (thus needs to be used in a synchronized manner) and
B) it may not be synchronized due to efficiency reasons.
The only advice I can give you is to perform as fine grained syncrhonization as possible, i.e. only synchronize over thread-unsafe parts of the method.
If for instance statement S1 needs to be performed atomically together with S2 you could instead of doing
public synchronized static Person fromName(String name){
...
S1;
S2;
...
return ...;
}
do
public static Person fromName(String name){
...
synchronized (lock) {
S1;
S2;
}
...
return ...;
}
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();