In this article we will learn one of core concept in Java that is Synchronization. if you want two threads to communicate and share a complicated data structure, such as a linked list, you need someway to ensure that they don’t conflict with each other. That is, you must prevent one thread from writing data while another thread is in the middle of reading it. For this purpose, Java implements an elegant twist on an age-old model of inter process synchronization.When two or more threads need access to a shared resource, they need some way to ensure that the resource will be used by only one thread at a time. The process by which this is achieved is called synchronization.
- Synchronized is the keyword applicable for methods and blocks
- We can not apply this keyword for variables and classes
- if a method declared synchronized at a time only one thread is allowed to execute that method on the given object.
Advantage:
The main advantage of the synchronized keyword is we can overcome data inconsistency problem.
Disadvantage:
- The main limitation of synchronized keyword is it may create preference problems
- Hence if there is no specific requirement it is not recommended to use synchronized keyword
lock on the object:
- Every object in java has a unique lock
- Whenever using synchronized keyword then object level lock concept will come into picture.
- If a thread want to execute any synchronized method on object first it should require the lock of that object.
- Once a thread got the lock then it is allowed to execute any synchronized method on that object
While a thread executing a synchronized method on that object, then the remaining threads are not allowed to execute any synchronized method on the same object.
But the remaining threads are allowed to execute any non-synchronized method on the same object.
Recommended to Read: Synchronization Interview Questions
Every object in java has unique lock but a thread can acquire more than one lock at a time:
Example:
class Display{
public synchronized void wish(String name){
for(int i=0;i<=10;i++){
System.out.print("hai.....");
try{
Thread.sleep(2000);
}
catch(InterruptedException e){
}
System.out.print(name);
}
}
}
class MyThread extends Thread{
Display d;
String name;
MyThread(Display d,String name){
MyThread(Display d,String name){
this.d=d;
this.name=name;
}
public void run(){
d.wish(name);
}
}
class SynchronizedDemo{
}
class SynchronizedDemo{
public static void main(String args[]){
Display d=new Display();
MyThread t1=new MyThread(d,"lucky");
MyThread t2=new MyThread(d,"reddy");
t1.start();
t2.start();
t2.start();
}
}
}
Output:
hai--------lucky
hai---------lucky
hai---------lucky
hai---------lucky
hai---------lucky
hai---------lucky
hai---------lucky
hai-------- lucky
hai---------lucky
hai-------- lucky
hai---------lucky
hai---------lucky
hai---------lucky
hai---------lucky
hai---------reddy
hai---------reddy
hai---------reddy
hai---------reddy
hai---------reddy
hai---------reddy
hai---------reddy
hai---------reddy
hai---------reddy
hai---------reddy
hai---------reddy
hai---------reddy
hai---------reddy
Note:
If we are not declaring wish method as synchronized we will get irregular output. Because the threads will execute simultaneously. If we are declaring wish method as synchronized we will get regular output.Because only thread will allow to execute wish method.
Synchronized block:
- It is not recommended to declare entire method as synchronized
- If very few lines of the code causes the problem that code we can declare inside synchronized block
- So that we cam improve the performance of the system.
Syntax:
synchronized(b)
{
//critical section
//critical section
}
Where 'b' is an object reference
To get the lock for the current object we can define synchronized block as fallows
To get the lock for the current object we can define synchronized block as fallows
synchronized(this)
{
//critical section
}
- we can define synchronized block to get class level as follows
synchronized(Display.class)
- we can define synchronized block either object reference or class reference
- But not for primitives violation leads to compile time error
Example:
class Callme {
void call(String msg) {
System.out.print("[" + msg);
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
System.out.println("Interrupted");
}
System.out.println("]");
}
}
class Caller implements Runnable {
String msg;
Callme target;
Thread t;
public Caller(Callme targ, String s) {
target = targ;
msg = s;
t = new Thread(this);
t.start();
}
// synchronize calls to call()
public void run() {
synchronized(target) { // synchronized block
target.call(msg);
}
}
}
class SynchronizedBlock {
public static void main(String args[]) {
Callme target = new Callme();
Caller ob1 = new Caller(target, "Hello");
Caller ob2 = new Caller(target, "Synchronized");
Caller ob3 = new Caller(target, "World");
// wait for threads to end
try {
ob1.t.join();
ob2.t.join();
ob3.t.join();
}
catch(InterruptedException e) {
System.out.println("Interrupted");
}
}
}
class Callme {
void call(String msg) {
System.out.print("[" + msg);
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
System.out.println("Interrupted");
}
System.out.println("]");
}
}
class Caller implements Runnable {
String msg;
Callme target;
Thread t;
public Caller(Callme targ, String s) {
target = targ;
msg = s;
t = new Thread(this);
t.start();
}
// synchronize calls to call()
public void run() {
synchronized(target) { // synchronized block
target.call(msg);
}
}
}
class SynchronizedBlock {
public static void main(String args[]) {
Callme target = new Callme();
Caller ob1 = new Caller(target, "Hello");
Caller ob2 = new Caller(target, "Synchronized");
Caller ob3 = new Caller(target, "World");
// wait for threads to end
try {
ob1.t.join();
ob2.t.join();
ob3.t.join();
}
catch(InterruptedException e) {
System.out.println("Interrupted");
}
}
}
Nice tutorial
ReplyDelete