Synchronization
synchronization is used to prevent thread interference and consistency problems while
working with multiple threads. i.e. at a time only one thread is allowed to
access any shared resource.
synchronization is categorized into
two types as depicted below:
Let us see the problem of multi
threading without using synchronization . Here we are creating a Table
class which contain printTable () method to print tables, two thread
classes say FirstThread, SecondThread and a Test class .
Test.java
package syncronizedmethod;
class Table
{
public void
printTable( int num)
{
for(int i=1;i<=10;i++)
{
System.out.println(num+"X"+i+"="+num*i +" "+Thread.currentThread().getName());
try
{
Thread.sleep(500);//sleeps the thread
for 500 milli seconds
}
catch
(InterruptedException e)
{
e.printStackTrace();
}
}
}
}
class FirstThread extends Thread
{
Table
t;
int num;
public FirstThread(Table t,int num)
{
this.t=t;
this.num=num;
}
public void run()
{
t.printTable(num);
}
}
class SecondThread extends Thread
{
Table
t;
int num;
public SecondThread(Table t,int num)
{
this.t=t;
this.num=num;
}
public void run()
{
t.printTable(num);
}
}
public class Test
{
public static void main(String[] args)
{
Table
t=new Table();
FirstThread
ft=new FirstThread(t, 5);
SecondThread
st=new SecondThread(t, 6);
ft.start();
st.start();
}
}
output:
5X1=5
Thread-0
6X1=6
Thread-1
6X2=12
Thread-1
5X2=10
Thread-0
5X3=15
Thread-0
6X3=18
Thread-1
5X4=20
Thread-0
6X4=24
Thread-1
6X5=30
Thread-1
5X5=25
Thread-0
5X6=30
Thread-0
6X6=36
Thread-1
6X7=42
Thread-1
5X7=35
Thread-0
6X8=48
Thread-1
5X8=40
Thread-0
6X9=54
Thread-1
5X9=45
Thread-0
5X10=50
Thread-0
6X10=60
Thread-1
as we can see in
the above output Thread-0(FirstThread) and Thread-1(SecondThread) are
interfering.
Synchronized
method
Now let us see the solution to the
above problem by using synchronized method. Here we are using same classes used
in the above example. But we are making the printTable() method as synchronized method by adding the keyword synchronized.
package syncronizedmethod;
class Table
{
public synchronized void printTable( int num)
{
for(int i=1;i<=10;i++)
{
System.out.println(num+"X"+i+"="+num*i +" "+Thread.currentThread().getName());
try
{
Thread.sleep(500);//sleeps the thread
for 500 milli seconds
}
catch
(InterruptedException e)
{
e.printStackTrace();
}
}
}
}
class FirstThread extends Thread
{
Table
t;
int num;
public FirstThread(Table t,int num)
{
this.t=t;
this.num=num;
}
public void run()
{
t.printTable(num);
}
}
class SecondThread extends Thread
{
Table
t;
int num;
public SecondThread(Table t,int num)
{
this.t=t;
this.num=num;
}
public void run()
{
t.printTable(num);
}
}
public class Test
{
public static void main(String[] args)
{
Table
t=new Table();
FirstThread
ft=new FirstThread(t, 5);
SecondThread
st=new SecondThread(t, 6);
ft.start();
st.start();
}
}
output:
5X1=5
Thread-0
5X2=10
Thread-0
5X3=15
Thread-0
5X4=20
Thread-0
5X5=25
Thread-0
5X6=30
Thread-0
5X7=35
Thread-0
5X8=40
Thread-0
5X9=45
Thread-0
5X10=50
Thread-0
6X1=6
Thread-1
6X2=12
Thread-1
6X3=18
Thread-1
6X4=24
Thread-1
6X5=30
Thread-1
6X6=36
Thread-1
6X7=42
Thread-1
6X8=48
Thread-1
6X9=54
Thread-1
6X10=60
Thread-1
How
it works?
synchronization
works based on Locks. If any thread wants to access synchronized
resource it has to acquire the lock and release the lock when it is done. so
that another thread can access it by acquiring the lock.
There are two types
of locks: 1) Locks with object
2)Locks
with class
synchronized block
synchronized
block is same as synchronized method except that the scope of the synchronized
block is small.
·
If you want apply synchronization for
entire method then we go for synchronized method.
·
If you want apply synchronization for
some part of the code then we go for synchronized block.
syntax:
synchronized(object reference){}
Test.java
package syncronizedmethod;
class Table
{
public void printTable( int num)
{
synchronized(this)
{
for(int i=1;i<=10;i++)
{
System.out.println(num+"X"+i+"="+num*i +" "+Thread.currentThread().getName());
try
{
Thread.sleep(500);//sleeps the thread
for 500 milli seconds
}
catch
(InterruptedException e)
{
e.printStackTrace();
}
}
}
}
}
class FirstThread extends Thread
{
Table
t;
int num;
public FirstThread(Table t,int num)
{
this.t=t;
this.num=num;
}
public void run()
{
t.printTable(num);
}
}
class SecondThread extends Thread
{
Table
t;
int num;
public SecondThread(Table t,int num)
{
this.t=t;
this.num=num;
}
public void run()
{
t.printTable(num);
}
}
public class Test
{
public static void main(String[] args)
{
Table
t=new Table();
FirstThread
ft=new FirstThread(t, 5);
SecondThread
st=new SecondThread(t, 6);
ft.start();
st.start();
}
}
Output:
5X1=5
Thread-0
5X2=10
Thread-0
5X3=15
Thread-0
5X4=20
Thread-0
5X5=25
Thread-0
5X6=30
Thread-0
5X7=35
Thread-0
5X8=40
Thread-0
5X9=45
Thread-0
5X10=50
Thread-0
6X1=6
Thread-1
6X2=12
Thread-1
6X3=18
Thread-1
6X4=24
Thread-1
6X5=30
Thread-1
6X6=36
Thread-1
6X7=42
Thread-1
6X8=48
Thread-1
6X9=54
Thread-1
6X10=60
Thread-1
static
synchronization
As we know synchronization
works based on Locks. If any thread wants to access synchronized
resource it has to acquire the lock and release the lock when it is done. so
that another thread can access it by acquiring the lock.
There are two types
of locks: 1) Locks with object
2)Locks
with class
Locks
with object:
·
every object has a lock. only one lock
per object.
Locks with class:
·
every class has a lock. only one lock
per class(for static methods)