Synchronization in java is the capability to
control the access of multiple threads to any shared resource.
Java Synchronization is better option where we want to
allow only one thread to access the shared resource.
Why
use Synchronization
The
synchronization is mainly used to
- To prevent thread
interference.
- To prevent
consistency problem.
There
are two types of thread synchronization mutual exclusive and inter-thread
communication.
- Mutual Exclusive
- Synchronized
method.
- Synchronized
block.
- static
synchronization.
- Cooperation
(Inter-thread communication in java)
Mutual Exclusive
Mutual
Exclusive helps keep threads from interfering with one another while sharing
data. This can be done by three ways in java:
- by synchronized
method
- by synchronized
block
- by static
synchronization
When
a method or block is declared as synchronized, only one thread can enter
into that method or block. When one thread is executing synchronized method or
block, the other threads which wants to execute that method or
block wait or suspend their execution until first thread is done with that
method or block. Thus avoiding the thread interference and achieving thread
safeness. This can be explained well with the help of an example.
Consider this example,
class
Shared
{
int i;
synchronized void SharedMethod()
{
Thread t = Thread.currentThread();
for(i = 0; i <= 1000; i++)
{
System.out.println(t.getName()+" : "+i);
}
}
}
public
class ThreadsInJava
{
public static void main(String[] args)
{
final Shared s1 = new Shared();
Thread t1 = new Thread("Thread -
1")
{
@Override
public void run()
{
s1.SharedMethod();
}
};
Thread t2 = new Thread("Thread -
2")
{
@Override
public void run()
{
s1.SharedMethod();
}
};
t1.start();
t2.start();
}
}
In
the above example, both threads t1 and t2 wants to execute sharedMethod() of s1
object. But, sharedMethod() is declared as synchronized. So, whichever thread
enters first into sharedMethod(), it continues to execute that method. The
other thread waits for first thread to finish it’s execution of sharedMethod().
It never enters into sharedMethod() until first thread is done with that
method. That means, both threads are executing sharedMethod() one by one not
simultaneously. This protects the value of “i” in the memory for a particular
thread.
The Logic Behind the Synchronization
in Java:
The
synchronization in java is built around an entity called object
lock or monitor. Here is the brief description
about lock or monitor.
·
Whenever an object is created to any
class, an object lock is created and is stored inside the object.
·
One object will have only one object lock
associated with it.
·
Any thread wants to enter into
synchronized methods or blocks of any object, they must acquire object
lock associated with that object and release the lock after they are done with
the execution.
·
The other threads which wants to enter
into synchronized methods of that object have to wait until the currently
executing thread releases the object lock.
·
To enter into static synchronized methods
or blocks, threads have to acquire class lock associated with that class as
static members are stored inside the class memory.
Synchronized Blocks:
Sometimes,
you need only some part of the method to be synchronized not the whole method.
This can be achieved with synchronized blocks. Synchronized blocks must be
defined inside a definition blocks like methods, constructors, static
initializer or instance initializer.
synchronized
block takes one argument and it is called mutex. if synchronized block is
defined inside non-static definition blocks like non-static methods, instance
initializer or constructors, then this mutex must be an instance of that class.
If synchronized block is defined inside static definition blocks like static
methods or static initializer, then this mutex must be like ClassName.class.
Here is an example of static and
non-static synchronized blocks.
class
Shared
{
static void staticMethod()
{
synchronized (Shared.class)
{
//static synchronized block
}
}
void NonStaticMethod()
{
synchronized (this)
{
//Non-static synchronized block
}
}
void anotherNonStaticMethod()
{
synchronized (new Shared())
{
//Non-static synchronized block
}
}
}
10 Points-To-Remember About
Synchronization In Java:
1) You can
use synchronized keyword only with methods but not with
variables, constructors, static initializer and instance initializers.
class
Shared
{
synchronized int i; //compile time error, can't use
synchronized keyword with variables
synchronized public Shared()
{
//compile time error, constructors can
not be synchronized
}
synchronized static
{
//Compile time error, Static
initializer can not be synchronized
}
synchronized
{
//Compile time error, Instance
initializer can not be synchronized
}
}
2) Constructors,
Static initializer and instance initializer can’t be declared with synchronized
keyword, but they can contain synchronized blocks.
class
Shared
{
public Shared()
{
synchronized (this)
{
//synchronized block inside a
constructor
}
}
static
{
synchronized (Shared.class)
{
//synchronized block inside a
static initializer
}
}
{
synchronized (this)
{
//synchronized block inside a
instance initializer
}
}
}
3) Both static
and non-static methods can use synchronized keyword. For static methods, thread
need class level lock and for non-static methods, thread need object level
lock.
class
Shared
{
synchronized static void staticMethod()
{
//static synchronized method
}
synchronized void NonStaticMethod()
{
//Non-static Synchronized method
}
}
4) It is
possible that both static synchronized and non-static synchronized methods can
run simultaneously. Because, static methods need class level lock and
non-static methods need object level lock.
5) A method can
contain any number of synchronized blocks. This is like synchronizing multiple
parts of a method.
class
Shared
{
static
void staticMethod()
{
synchronized
(Shared.class)
{
//static
synchronized block - 1
}
synchronized
(Shared.class)
{
//static
synchronized block - 2
}
}
void
NonStaticMethod()
{
synchronized
(this)
{
//Non-static
Synchronized block - 1
}
synchronized
(this)
{
//Non-static
Synchronized block - 2
}
}
}
6) Synchronization
blocks can be nested.
synchronized
(this)
{
synchronized (this)
{
//Nested synchronized blocks
}
}
7) Lock
acquired by the thread before executing a synchronized method or block must
be released after the completion of execution, no matter whether execution
is completed normally or abnormally (due to exceptions).
8) Synchronization
in java is Re-entrant in nature. A thread can not acquire a lock
that is owned by another thread. But, a thread can acquire a lock that it
already owns. That means if a synchronized method gives a call to another
synchronized method which needs same lock, then currently executing thread
can directly enter into that method or block without acquiring the lock.
9) synchronized
method or block is very slow. They decrease the performance of an application.
So, special care need to be taken while using synchronization. Use
synchronization only when you needed it the most.
10) Use
synchronized blocks instead of synchronized methods. Because, synchronizing
some part of a method improves the performance than synchronizing the whole
method.
No comments:
Post a Comment