Why is synchronized block better than synchronized method? - java

I have started learning synchronization in threading.
Synchronized method:
public class Counter {
private static int count = 0;
public static synchronized int getCount() {
return count;
}
public synchronized setCount(int count) {
this.count = count;
}
}
Synchronized block:
public class Singleton {
private static volatile Singleton _instance;
public static Singleton getInstance() {
if (_instance == null) {
synchronized(Singleton.class) {
if (_instance == null)
_instance = new Singleton();
}
}
return _instance;
}
}
When should I use synchronized method and synchronized block?
Why is synchronized block better than synchronized method ?

It's not a matter of better, just different.
When you synchronize a method, you are effectively synchronizing to the object itself. In the case of a static method, you're synchronizing to the class of the object. So the following two pieces of code execute the same way:
public synchronized int getCount() {
// ...
}
This is just like you wrote this.
public int getCount() {
synchronized (this) {
// ...
}
}
If you want to control synchronization to a specific object, or you only want part of a method to be synchronized to the object, then specify a synchronized block. If you use the synchronized keyword on the method declaration, it will synchronize the whole method to the object or class.

The difference is in which lock is being acquired:
synchronized method acquires a lock on the whole object. This means no other thread can use any synchronized method in the whole object while the method is being run by one thread.
synchronized blocks acquires a lock in the object between parentheses after the synchronized keyword. Meaning no other thread can acquire a lock on the locked object until the synchronized block exits.
So if you want to lock the whole object, use a synchronized method. If you want to keep other parts of the object accessible to other threads, use synchronized block.
If you choose the locked object carefully, synchronized blocks will lead to less contention, because the whole object/class is not blocked.
This applies similarly to static methods: a synchronized static method will acquire a lock in the whole class object, while a synchronized block inside a static method will acquire a lock in the object between parentheses.

Although not usually a concern, from a security perspective, it is better to use synchronized on a private object, rather than putting it on a method.
Putting it on the method means you are using the lock of the object itself to provide thread safety. With this kind of mechanism, it is possible for a malicious user of your code to also obtain the lock on your object, and hold it forever, effectively blocking other threads. A non-malicious user can effectively do the same thing inadvertently.
If you use the lock of a private data member, you can prevent this, since it is impossible for a malicious user to obtain the lock on your private object.
private final Object lockObject = new Object();
public void getCount() {
synchronized( lockObject ) {
...
}
}
This technique is mentioned in Bloch's Effective Java (2nd Ed), Item #70

Difference between synchronized block and synchronized method are following:
synchronized block reduce scope of lock, but synchronized method's scope of lock is whole method.
synchronized block has better performance as only the critical section is locked but synchronized method has poor performance than block.
synchronized block provide granular control over lock but synchronized method lock either on current object represented by this or class level lock.
synchronized block can throw NullPointerException but synchronized method doesn't throw.
synchronized block:
synchronized(this){}
synchronized method:
public synchronized void fun(){}

Define 'better'. A synchronized block is only better because it allows you to:
Synchronize on a different object
Limit the scope of synchronization
Now your specific example is an example of the double-checked locking pattern which is suspect (in older Java versions it was broken, and it is easy to do it wrong).
If your initialization is cheap, it might be better to initialize immediately with a final field, and not on the first request, it would also remove the need for synchronization.

synchronized should only be used when you want your class to be Thread safe. In fact most of the classes should not use synchronized anyways. synchronized method would only provide a lock on this object and only for the duration of its execution. if you really wanna to make your classes thread safe, you should consider making your variables volatile or synchronize the access.
one of the issues of using synchronized method is that all of the members of the class would use the same lock which will make your program slower. In your case synchronized method and block would execute no different. what I'd would recommend is to use a dedicated lock and use a synchronized block something like this.
public class AClass {
private int x;
private final Object lock = new Object(); //it must be final!
public void setX() {
synchronized(lock) {
x++;
}
}
}

In your case both are equivalent!
Synchronizing a static method is equivalent to a synchronized block on corresponding Class object.
In fact when you declare a synchronized static method lock is obtained on the monitor corresponding to the Class object.
public static synchronized int getCount() {
// ...
}
is same as
public int getCount() {
synchronized (ClassName.class) {
// ...
}
}

One classic difference between Synchronized block and Synchronized method is that Synchronized method locks the entire object. Synchronized block just locks the code within the block.
Synchronized method: Basically these 2 sync methods disable multithreading. So one thread completes the method1() and the another thread waits for the Thread1 completion.
class SyncExerciseWithSyncMethod {
public synchronized void method1() {
try {
System.out.println("In Method 1");
Thread.sleep(5000);
} catch (Exception e) {
System.out.println("Catch of method 1");
} finally {
System.out.println("Finally of method 1");
}
}
public synchronized void method2() {
try {
for (int i = 1; i < 10; i++) {
System.out.println("Method 2 " + i);
Thread.sleep(1000);
}
} catch (Exception e) {
System.out.println("Catch of method 2");
} finally {
System.out.println("Finally of method 2");
}
}
}
Output
-------
In Method 1
Finally of method 1
Method 2 1
Method 2 2
Method 2 3
Method 2 4
Method 2 5
Method 2 6
Method 2 7
Method 2 8
Method 2 9
Finally of method 2
Synchronized block: Enables multiple threads to access the same object at same time [Enables multi-threading].
class SyncExerciseWithSyncBlock {
public Object lock1 = new Object();
public Object lock2 = new Object();
public void method1() {
synchronized (lock1) {
try {
System.out.println("In Method 1");
Thread.sleep(5000);
} catch (Exception e) {
System.out.println("Catch of method 1");
} finally {
System.out.println("Finally of method 1");
}
}
}
public void method2() {
synchronized (lock2) {
try {
for (int i = 1; i < 10; i++) {
System.out.println("Method 2 " + i);
Thread.sleep(1000);
}
} catch (Exception e) {
System.out.println("Catch of method 2");
} finally {
System.out.println("Finally of method 2");
}
}
}
}
Output
-------
In Method 1
Method 2 1
Method 2 2
Method 2 3
Method 2 4
Method 2 5
Finally of method 1
Method 2 6
Method 2 7
Method 2 8
Method 2 9
Finally of method 2

It should not be considered as a question of best for usage, but it really depends on the use case or the scenario.
Synchronized Methods
An entire method can be marked as synchronized resulting an implicit lock on the this reference (instance methods) or class (static methods). This is very convenient mechanism to achieve synchronization.
Steps
A thread access the synchronized method. It implicitly acquires the lock and execute the code.
If other thread want to access the above method, it has to wait. The thread can't get the lock, will be blocked and has to wait till the lock is released.
Synchronized Blocks
To acquire a lock on an object for a specific set of code block, synchronized blocks are the best fit. As a block is sufficient, using a synchronized method will be a waste.
More specifically with Synchronized Block , it is possible to define the object reference on which are want to acquire a lock.

Because lock is expensive, when you are using synchronized block you lock only if _instance == null, and after _instance finally initialized you'll never lock. But when you synchronize on method you lock unconditionally, even after the _instance is initialized. This is the idea behind double-checked locking optimization pattern http://en.wikipedia.org/wiki/Double-checked_locking.

Related

java, synchronized in two separate methods?

I'm trying to create thread safe queue in java. I've come across this example:
class ProducerConsumer<T> {
private static final int BUFFER_MAX_SIZE = 42;
private List<T> buffer = new LinkedList<>();
synchronized void produce(T value) throws InterruptedException {
while (buffer.size() == BUFFER_MAX_SIZE) {
wait();
}
buffer.add(value);
notify();
}
synchronized T consume() throws InterruptedException {
while (buffer.size() == 0) {
wait();
}
T result = buffer.remove(0);
notify();
return result;
}
}
I'm new to java. In my understanding those two 'synchronized' keywords would prevent contention inside each method, but not when both methods are called simultaneously. E.g. thread P calls produce, locks method, thread C calls consume, locks other method, then one tries to extract element from list, another tries to insert element, thread exception arises.
My question: Is this example broken?
Or maybe I'm missing something and it's ok.
JLS, §17.1 is quite explicit about the mechanism:
...
A synchronized method (§8.4.3.6) automatically performs a lock action when it is invoked; its body is not executed until the lock action has successfully completed. If the method is an instance method, it locks the monitor associated with the instance for which it was invoked (that is, the object that will be known as this during execution of the body of the method). If the method is static, it locks the monitor associated with the Class object that represents the class in which the method is defined. If execution of the method's body is ever completed, either normally or abruptly, an unlock action is automatically performed on that same monitor.
...
Thus, it is guaranteed that at one point in time on one object at most one thread is executing either produce(...) or consume(). It is not possible that, at one point in time, one thread executes produce(...) on an object while another thread executes consume() on the same object.
The call to wait() in consume() releases the intrinsic lock and blocks execution. The call to notify() in produce(...) notifies one wait()ing thread (if any), so it can fight for the lock as soon as the lock is released by the current owner. Notice that a call to notify() does not release the intrinsic lock. It just wakes up a wait()ing thread. This can be made observable with the following code snippet:
class Ideone {
private static final Object lock = new Object();
public static void main(String[] args) {
printWithThreadNamePrefix("Start");
Thread waiter = new Thread(Ideone::waiter);
waiter.start();
// Give waiter some time to a) start and b) acquire the intrinsic lock
try {
Thread.sleep(500);
} catch (InterruptedException e) {
}
final Thread notifier = new Thread(Ideone::notifier);
notifier.start();
while (true) {
try {
waiter.join();
break;
} catch (InterruptedException e) {
}
}
printWithThreadNamePrefix("End");
}
private static void waiter() {
synchronized (lock) {
printWithThreadNamePrefix("Waiting...");
while (true) {
try {
lock.wait();
break;
} catch (InterruptedException e) {
}
}
printWithThreadNamePrefix("... done waiting");
}
}
private static void printWithThreadNamePrefix(String msg) {
System.out.println(String.format(
"%s: %s",
Thread.currentThread().getName(),
msg));
}
private static void notifier() {
synchronized (lock) {
printWithThreadNamePrefix("notifying");
lock.notify();
while (true) {
}
}
}
}
Ideone demo
The program will never terminate. Although thread two calls notify(), it then enters an endless loop, never actually releasing the intrinsic lock. Thus, one never has a chance to acquire the intrinsic lock, and the program "hangs" (it is neither a deadlock, nor a livelock, it simply cannot proceed).
The things I recommend to change are:
declare private List<T> buffer additionally as final
call notifyAll() instead of notify() in order to wake all waiting threads (they will still execute sequentially, for details see this question by Sergey Mikhanov and its answers)

(Java) Thread safety using Object wait() and notify()

I was looking for a way to make one thread wait/sleep until another thread signalled that something was ready. The waiting thread should wake up, process the data that was made available, then go back to sleep until the other thread signalled again.
The simplest method I could find was Object.wait() and Object.notify(), which behaved like a semaphore initialised to value 0. However, without the synchronized statements around notify/wait, Java always threw IllegalMonitorStateException when the thread was not the monitor owner. So I simply put them around the code like shown below.
THREAD 1: running infinite loop
public class Main {
private Handler handler; // only one instance (singleton pattern)
public void listen() {
while (true) {
try {
synchronized (handler) {
handler.wait();
int value = handler.getSize();
// do something
}
} catch (InterruptedException e) {
// ...
}
}
}
}
THREAD 2: Some other class calls removeItem
public class Handler {
// SINGLETON PATTERN - ONLY ONE INSTANCE
private ArrayList<Integer> sharedList;
private Handler() {
sharedList = new ArrayList<>();
}
public void addItem(Integer i) {
synchronized (sharedList) {
// add to list
}
}
public void removeItem(int i) {
synchronized (sharedList) {
// remove item
// notify that something is removed
synchronized (this) {
this.notify(); // this == handler
}
}
}
public int getSize() {
synchronized (sharedList) {
return sharedList.size();
}
}
}
It seems to work perfectly fine but not sure if there is a hidden bug.
My question is: Is this safe? Does wait release the instance lock for handler/this so notify can acquire the lock?
Synchronized blocks are safe. The statement synchronized(obj) acquires the lock of the argument obj, so you can call wait and notify on it. They both require that the current thread holds the lock on the object.
You have to be careful about the double-locking you have in removeItem where you lock two objects. If you ever need this, you have to make sure that you always lock them in the same order, otherwise, you may create a deadlock.

Synchronizing static methods

I'm writing code that requires some synchronization between a few static methods. My goal is to block the execution of any of these methods if one of them executes.
So for example:
public class Foo{
static Object lock = new Object();
static List<SomeObject> listOfObjects = new ArrayList<>() ;
public static void methodA() {
synchronized (lock) {
//Do some stuff
methodB();
}
}
public static List<SomeObject> methodB() {
synchronized (lock) {
//Do some stuff
return listOfObjects;
}
}
}
Now let's assume that the following is executed from somewhere in the code:
Foo.methodA();
Foo.methodB();
My questions are:
Is it actually synchronized? will methodA and methodB won't run concurrently?
If so, will methodA calling methodB create a deadlock?
Answers:
"Is it actually synchronized? will methodA and methodB won't run
concurrently?" - yes, these methods are synchronised. More precisely, code blocks in methods are synchronised.
"If so, will methodA calling methodB create a deadlock?" - no, synchronized keyword is re-entrant in nature it means if a synchronized method calls another synchronized method which requires same lock then current thread which is holding lock can enter into that method without acquiring lock" - from 1
You could improve code a little by providing private and final keywords:
private static final Object lock = new Object();
Also, do not return direct reference to a List you want to protect. Return read only view:
return Collections.unmodifiableList(listOfObjects);
Since now, client has only read only access which protects you from many unexpected situations.
Static versus non-static lock object in synchronized block
Object level lock vs Class level lock in Java
Is it actually synchronized? will methodA and methodB won't run
concurrently?
Yes, this synchronization looks good.
A thread can acquire the same lock multiple times, increasing a lock counter. And after it releases all of them, only then another thread can acquire that lock.
In your code, a thread calling methodA() acquires the lock twice, once in methodA() and then in methodB(). Then it releases them twice (when the synchronized blocks end).
If so, will methodA calling methodB create a deadlock?
No, as explained above, it won't create a deadlock unless you are doing some operations in those methods that can take forever to complete, in which case there will be starvation. If you are not doing any such operation, then I don't think you can get a deadlock when you are using only one lock.
Nope. Method A and method B WILL run concurrently because it's not the methods that are synchronized but the code inside. The code will continue normally with whichever has the lock. Then the other method will finish.
public class Foo1 {
static Object lock = new Object();
static List<Integer> listOfObjects = new ArrayList<>();
public static void main(String[] args) {
new Foo1().start();
}
public void start() {
new Thread(() -> methodA()).start();
// method A has the lock
sleep(1000); // sleep 1 second
// but method B is still entered and prints first
new Thread(() -> methodB()).start();
}
public static void methodA() {
sleep(5000); // sleep 5 seconds
System.out.println("Entering methodA()");
synchronized (lock) {
// Do some stuff
methodB();
}
}
public static List<Integer> methodB() {
System.out.println("Entering methodB()");
synchronized (lock) {
// Do some stuff
return listOfObjects;
}
}
static void sleep(int milli) {
try {
Thread.sleep(milli);
}
catch (InterruptedException ie) {
}
}
}

java synchronized

The Class X have two methods: test and test1.
I've created two threads: t1 and t2. Thread t1 is accessing test method and t2 is accessing test1 method of same object. When t1 is accessing test method which synchronized it acquires lock on object.
Will t2 be able to access test1 method on same object? Why it is able to access this method if t1 has a lock on it?
If I'm executing the following code
X x = new X();
new MyThread(x).start(); // It execute test() method
new MyThread1(x).start();// It execute test1() method
class X
{
String a = "varsha";
public synchronized void test ()
{
try
{
Thread.sleep (6000);
}
catch (InterruptedException e)
{
e.printStackTrace ();
}
}
public void test1 ()
{
synchronized (a)
{
}
}
}
You have two different locks:
test() locks this;
test1() locks this.a.
The two locks are completely independent and thus the two methods can be called at the same time.
Your code is equivalent to the following:
class X
{
String a = "varsha";
public void test ()
{
synchronized (this)
{
try
{
Thread.sleep (6000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
public void test1 ()
{
synchronized(a)
{
}
}
}
So these methods are synchronizing at different objects (this versus a) and thus can be executed concurrently without locking each other.
Note, that I replaced Thread.currentThread ().sleep (6000) with Thread.sleep (6000) because method sleep is static and thus you don't need any instance of Thread in order to use it.
class X {
String a = "varsha";
public synchronized void test(){
try {
//if you are modifying the instance variable here
// then the test1() synchronized block will
//not be given lock permission to t2 thread
// synchronization is for thread safety.
// In your example you are not modifying the instance variable.
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void test1(){
synchronized(a){
}
}
}
Here is whats actually happening.
Every object in Java has a "monitor lock", In this case object "x".
There are two threads (MyThread and MyThread1) trying to acquire this lock in the following sequence -
Imagine there is a queue – MyThread is in front of MyThread1 in this queue because you have started MyThread first followed by MyThread1.
MyThread acquires the lock first and it starts executing, you have invoked the sleep() method on it. This will change the state of MyThread from "execution state" to "waiting state" and then to "ready state", it will release the lock at this moment since it is not in execution state. At this point MyThread1 is ahead in the queue and it acquires the lock and starts executing.
This is in a way similar to the concept of "Context Switch". Refer book - Operating System Internals and Design.
When you mark a method as synchronized, it locks the object for that method; meaning no other thread can access that PARTICULAR method for that object. In your case no other thread can access the test method; but of course test1 method can be accessed.

If a synchronized method calls another non-synchronized method, is there a lock on the non-synchronized method

In Java, if a synchronized method contains a call to a non-synchronized, can another method still access the non-synchronized method at the same time? Basically what I'm asking is everything in the synchronized method have a lock on it (including calls to other synchronized methods)?
If a synchronized method calls another non-synchronized method, is there a lock on the non-synchronized method
The answer depends on the context.
If you are in a synchronized method for an object, then calls by other threads to other methods of the same object instance that are also synchronized are locked. However calls by other threads to non-synchronized methods are not locked – anyone can call them at the same time.
public synchronized void someSynchronizedMethod() {
...
someNonSynchronizedMethod();
...
}
// anyone can call this method even if the someSynchronizedMethod() method has
// been called and the lock has been locked
public void someNonSynchronizedMethod() {
...
}
Also, if you call someSynchronizedMethod() but happen to be within the someNonSynchronizedMethod() method, you still hold the lock. The lock is enabled when you enter a synchronized method (or block) and is disabled when you exit that method. You can call all sorts of other unsynchronized methods and they will still be locked.
But you are asking two different things in your question:
In Java, if a synchronized method contains a call to a non-synchronized, can another method still access the non-synchronized method at the same time?
Yes. Other methods can access non-synchronized methods.
Basically what I'm asking is everything in the synchronized method have a lock on it (including calls to other synchronized methods)?
Uh, yes. Other calls to synchronized methods are locked. But non-synchronized methods are not locked.
Also, remember that if the method is static then the lock is on the Class object in the ClassLoader.
// this locks on the Class object in the ClassLoader
public static synchronized void someStaticMethod() {
If the method is an instance method then the lock is on the instance of the class.
// this locks on the instance object that contains the method
public synchronized void someInstanceMethod() {
There are 2 different locks in those 2 cases.
Lastly, when you are dealing with synchronized instance methods, each instance of the class is what is locked. This means that two threads could be in the same synchronized method at the same time with different instances. But if 2 threads try to operate on synchronized methods on the same instance, one will block until the other one exits the method.
If thread A calls synchronized method M1 which in turn calls unsynchronized method M2, then thread B can still call M2 without blocking.
Synchronized method acquires and releases intrinsic lock on the object on which it is called. This is why it may block. Unsynchronized method doesn't attempt to acquire any lock (unless it is done explicitly in the code).
Thus, if you need to ensure mutual exclusion for M2 as well, you should make it synchronized regardless of whether its callers (like M1) are synchronized or not.
The lock doesn't belong to the thread. The lock actually belongs to the object(or Class in case of Class level lock), and a thread acquires lock on the Object(or Class in case of Class level lock) within a synchronized context.
Now, there is no lock propagation in java as it is discussed above. Here is a small demo:
public class TestThread {
/**
* #param args
* #throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
// TODO Auto-generated method stub
ThreadCreator1 threadCreator1 = new ThreadCreator1();
ThreadCreator2 threadCreator2 = new ThreadCreator2();
Thread t1 = new Thread(threadCreator1,"Thread 1");
Thread t3 = new Thread(threadCreator1,"Thread 3");
Thread t2 = new Thread(threadCreator2,"Thread 2");
t1.start();
Thread.sleep(2000);
t3.start();
}
}
public class ThreadCreator1 implements Runnable {
private static final Task task= new Task();
private static final Task2 task2= new Task2();
#Override
public void run() {
try {
if(Thread.currentThread().getName().equals("Thread 1"))
task.startTask2(task2);
if(Thread.currentThread().getName().equals("Thread 3"))
task2.startTask();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// TODO Auto-generated method stub
/**/
}
}
public class Task {
public static final Task task = new Task();
public static List<String> dataList = new ArrayList<String>();
ReentrantLock lock = new ReentrantLock();
public void startTask2(Task2 task2) throws InterruptedException
{
try{
lock.lock();
//new Task2().startTask();
task2.startTask();
}
catch(Exception e)
{
}
finally{
lock.unlock();
}
}
}
public class Task2 {
ReentrantLock lock = new ReentrantLock();
public void startTask() throws InterruptedException
{
try{
//lock.lock();
for(int i =0 ;i< 10;i++)
{
System.out.println(" *** Printing i:"+i+" for:"+Thread.currentThread().getName());
Thread.sleep(1000);
}
}
catch(Exception e)
{
}
/*finally
{
lock.unlock();
}*/
}
}
Just I have used Reentrant lock here.
If the above code is run, then there will be interleaving between thread 1 and thread 3, but if the lock portion of Task2 class is uncommented, then there will be no interleaving and the thread which acquire the lock first will complete fully first, then it will release the lock and then the other thread can carry on.
The lock belongs to the thread, not to the method (or more precisely, its stack frame). It just so happens that if you have a synchronized method, you're guaranteed that the thread will own the lock before the body of the method start, and will release it afterwards.
Another thread can still invoke the second, non-synchronized method. An unsynchronized method can be called by any thread at any time.

Categories