0% found this document useful (0 votes)
24 views19 pages

Synchronization in Java

Uploaded by

susmithamadineni
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
Download as docx, pdf, or txt
0% found this document useful (0 votes)
24 views19 pages

Synchronization in Java

Uploaded by

susmithamadineni
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1/ 19

Synchronization in Java

In Java, synchronization refers to the ability to control


the access of multiple threads to any shared resource. It is an
ideal option where we want to allow only one thread to access
the shared resource.
Synchronization is a process of controlling mutual
exclusive problem in multithreading environment. Only one
thread can access a resource at a particular instance of time.
When a thread accesses a synchronized block or method, it
acquires a lock on it and release the lock either after
completion of method/block or any exception occur.
Note:

1. Synchronization in java is not needed in case of


immutable objects.
2. Synchronized keyword is used for performing
synchronization in java.
3. Variables can’t be synchronized in java. It will give
compile time error.
Types of Synchronization
There are two types of synchronization methods in Java:
1) Process synchronization
2) Thread synchronization.
Process synchronization:
Process Synchronization is a technique used to
coordinate the execution of multiple processes. It ensures that
the shared resources are safe and in order. For example,
programs such as `Microsoft Word` and `Acrobat reader` run
as individual processes.
Thread synchronization: Thread Synchronization is used to
coordinate and ordering of the execution of the threads in a
multi-threaded program. There are two types of thread
synchronization are mentioned below:
 Mutual Exclusive
 Cooperation (Inter-thread communication in Java)

Mutual Exclusive:

Mutual Exclusive helps keep threads from interfering with


one another while sharing data. There are three types of
Mutual Exclusive mentioned below:
 Synchronized method.

 Synchronized block.

 Static synchronization.

Lock in Java:
Synchronization is built around an internal entity known as
the lock or monitor. Every object has a lock associated with it.
By convention, a thread that needs consistent access to an
object's fields has to acquire the object's lock before accessing
them, and then release the lock when it's done with them.
From Java 5 the package java.util.concurrent.locks contains
several lock implementations.
Synchronized method:
When we declare a synchronized keyword in the header of a
method, it is called synchronized method in Java.
Using the synchronized keyword, we can synchronize all the
methods of any class.
When a method is declared as synchronized, JVM creates a
monitor (lock). To enter the monitor, the synchronized
method is called. The thread that calls the synchronized
method first, acquires object lock.
If the object lock is not available, the calling thread is blocked
and it has to wait until the lock becomes available.
As long as thread holds lock (monitor), no other thread can
enter the synchronized method and will have to wait for the
current thread to release the lock on the same object.
Once a thread completes the execution of code inside the
synchronized method, it releases object lock and allows other
thread waiting for this lock to proceed.
That is once a thread completes its work using synchronized
method, it will hand over to the next thread that is ready to use
the same resource.
Syntax:
synchronized data_type method_name()
{
// Code to be synchronized.
}

Understanding the problem without Synchronization


class Table{
void printTable(int n){//method not synchronized
for(int i=1;i<=5;i++){
System.out.println(n*i);
try{
Thread.sleep(400);
}catch(Exception e){System.out.println(e);}
}

}
}

class MyThread1 extends Thread{


Table t;
MyThread1(Table t){
this.t=t;
}
public void run(){
t.printTable(5);
}

}
class MyThread2 extends Thread{
Table t;
MyThread2(Table t){
this.t=t;
}
public void run(){
t.printTable(100);
}
}

class TestSynchronization1{
public static void main(String args[]){
Table obj = new Table();//only one object
MyThread1 t1=new MyThread1(obj);
MyThread2 t2=new MyThread2(obj);
t1.start();
t2.start();
}
}
Output:
5
100
10
200
15
300
20
400
25
500

//example of java synchronized method


class Table{
synchronized void printTable(int n){//synchronized metho
d
for(int i=1;i<=5;i++){
System.out.println(n*i);
try{
Thread.sleep(400);
}catch(Exception e){System.out.println(e);}
}

}
}
class MyThread1 extends Thread{
Table t;
MyThread1(Table t){
this.t=t;
}
public void run(){
t.printTable(5);
}

}
class MyThread2 extends Thread{
Table t;
MyThread2(Table t){
this.t=t;
}
public void run(){
t.printTable(100);
}
}

public class TestSynchronization2{


public static void main(String args[]){
Table obj = new Table();//only one object
MyThread1 t1=new MyThread1(obj);
MyThread2 t2=new MyThread2(obj);
t1.start();
t2.start();
}
}
Output:
5
10
15
20
25
100
200
300
400
500

Synchronized block:
Synchronized block in Java is another way of managing the
execution of threads. It is mainly used to perform
synchronization on a certain block of code or statements
inside the method.
Synchronizing a block of code is more powerful
than synchronized method.
For example, suppose there are 30 lines of code in a method,
but we want to synchronize only 5 lines of code. In this case,
we should use a synchronized block.
If we place all the codes of the method in the synchronized
block, it will work the same as the synchronized method.
Syntax:
synchronized(object)
{
// statements or codes to be synchronized.
}

In the above syntax, object represents an object reference to


be locked or synchronized. The code within synchronized
block is all available to only one thread at a time. They will
not available to more than one thread at a time.
Once a thread has entered inside the synchronized block after
acquiring lock on the specified object, other threads are
blocked to wait for the object lock on the same instance.
class Table
{
void printTable(int n){
synchronized(this){//synchronized block
for(int i=1;i<=5;i++){
System.out.println(n*i);
try{
Thread.sleep(400);
}catch(Exception e){System.out.println(e);}
}
}
}//end of the method
}

class MyThread1 extends Thread{


Table t;
MyThread1(Table t){
this.t=t;
}
public void run(){
t.printTable(5);
}

}
class MyThread2 extends Thread{
Table t;
MyThread2(Table t){
this.t=t;
}
public void run(){
t.printTable(100);
}
}

public class TestSynchronizedBlock1{


public static void main(String args[]){
Table obj = new Table();//only one object
MyThread1 t1=new MyThread1(obj);
MyThread2 t2=new MyThread2(obj);
t1.start();
t2.start();
}
}
Output:
5
10
15
20
25
100
200
300
400
500

Static Synchronization

a static method can also be synchronized. In this case, the lock


is placed on the class, not on the object. The thread will
execute the method body only when the lock is placed on the
class.
It will hold the lock until it leaves the method body. This is
called static synchronization in java.

class Table
{
synchronized static void printTable(int n){
for(int i=1;i<=10;i++){
System.out.println(n*i);
try{
Thread.sleep(400);
}catch(Exception e){}
}
}
}
class MyThread1 extends Thread{
public void run(){
Table.printTable(1);
}
}
class MyThread2 extends Thread{
public void run(){
Table.printTable(10);
}
}
class MyThread3 extends Thread{
public void run(){
Table.printTable(100);
}
}
class MyThread4 extends Thread{
public void run(){
Table.printTable(1000);
}
}
public class TestSynchronization4{
public static void main(String t[]){
MyThread1 t1=new MyThread1();
MyThread2 t2=new MyThread2();
MyThread3 t3=new MyThread3();
MyThread4 t4=new MyThread4();
t1.start();
t2.start();
t3.start();
t4.start();
}
}

Output:
1
2
3
4
5
6
7
8
9
10
10
20
30
40
50
60
70
80
90
100
100
200
300
400
500
600
700
800
900
1000
1000
2000
3000
4000
5000
6000
7000
8000
9000
10000
Inter-thread Communication in Java:
Inter-thread communication in Java is a technique through
which multiple threads communicate with each other.
It provides an efficient way through which more than one
thread communicate with each other by reducing CPU idle
time. CPU idle time is a process in which CPU cycles are not
wasted.
When more than one threads are executing simultaneously,
sometimes they need to communicate with each other by
exchanging information with each other. A thread exchanges
information before or after it changes its state.
There are several situations where communication between
threads is important.
For example, suppose that there are two threads A and B.
Thread B uses data produced by Thread A and performs its
task.
If Thread B waits for Thread A to produce data, it will waste
many CPU cycles. But if threads A and B communicate with
each other when they have completed their tasks, they do not
have to wait and check each other’s status every time.
Thus, CPU cycles will not waste. This type of information
exchanging between threads is called inter-thread
communication in Java.

How to achieve Inter thread communication in Java:


Inter thread communication in Java can be achieved by using
three methods provided by Object class of java.lang package.
They are:
1. wait()
2. notify()
3. notifyAll()
These methods can be called only from within a synchronized
method or synchronized block of code otherwise, an
exception named IllegalMonitorStateException is thrown.
All these methods are declared as final. Since it throws a
checked exception, therefore, you must be used these methods
within Java try-catch block.
wait() Method:
wait() method in Java notifies the current thread to give up the
monitor (lock) and to go into sleep state until another thread
wakes it up by calling notify() method. This method throws
InterruptedException. Various forms of wait() method allow
us to specify the amount of time a thread can wait.
public final void wait()
public final void wait(long millisecond) throws
InterruptedException
public final void wait(long millisecond, long nanosecond)
throws InterruptedException

notify() Method:
The notify() method wakes up a single thread that called
wait() method on the same object. If more than one thread is
waiting, this method will awake one of them. The general
syntax to call notify() method is as follows:
Syntax:
public final void notify()

notifyAll() Method:
The notifyAll() method is used to wake up all threads that
called wait() method on the same object. The thread having
the highest priority will run first.
Syntax:
public final void notifyAll()
Understanding the process of inter-thread
communication:

The point to point explanation of the above diagram is as


follows:
1. Threads enter to acquire lock.
2. Lock is acquired by on thread.
3. Now thread goes to waiting state if you call wait()
method on the object. Otherwise it releases the lock and
exits.
4. If you call notify() or notifyAll() method, thread moves
to the notified state (runnable state).
5. Now thread is available to acquire lock.
6. After completion of the task, thread releases the lock and
exits the monitor state of the object.
// A correct implementation of Producer and Consumer.
public class Q
{
int i;
boolean valueSet = false;
synchronized void produce(int i)
{
if(valueSet)
try
{
wait();
}
catch(InterruptedException ie)
{
System.out.println(ie);
}
this.i = i;
valueSet = true;
System.out.println("Data Produced: " +i);
notify();
}
synchronized int consume()
{
if(!valueSet)
try {
wait();
}
catch(InterruptedException ie){
System.out.println(ie);
}
System.out.println("Data Consumed: " + i);
valueSet = false;
notify();
return I;
}
}
public class Producer extends Thread
{
Q q;
Producer(Q q)
{
this.q = q;
}
public void run()
{
for(int j = 1; j <= 5; j++) {
q.produce(j);
}
}
}
public class Consumer extends Thread
{
Q q;
Consumer(Q q)
{
this.q = q;
}
public void run()
{
for(int k = 0; k <= 5; k++) {
q.consume();
}
}
}
public class ThreadCommunication {
public static void main(String[] args)
{
Q q = new Q();

Producer p = new Producer(q);


Consumer c = new Consumer(q);
p.start();
c.start();
}
}
Output:
Data Produced: 1
Data Consumed: 1
Data Produced: 2
Data Consumed: 2
Data Produced: 3
Data Consumed: 3
Data Produced: 4
Data Consumed: 4
Data Produced: 5
Data Consumed: 5

You might also like