This page a collection of useful links for Java/J2EE Technology article and tutorials.
1: Java Security:
http://www.ibm.com/developerworks/java/tutorials/j-sec1/
2: Java Design Patterns:
http://www.oodesign.com/
3: Excellent Java Website:
http://www.java2s.com/
This blog contains my understanding and research examples in Java language. All information is only for information/discussion purpose.
Tuesday, November 2, 2010
Difference Between Synchronized and ReentrantLock
Gnerally we think we can improve performence using ReentrantLock instead of synchronized block. During my understanding I found one situation where ReentrantLock was not able to replace synchronized.
ReentrantLock object can not take lock on specified object.
Example:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class AtomicTest {
public static void main(String[] args) throws Exception {
AtomicTest at = new AtomicTest();
SharedObject so = at.new SharedObject();
SyncProcessor sp1 = at.new SyncProcessor(so, "One", 1500);
SyncProcessor sp2 = at.new SyncProcessor(so, "Two", 1);
Thread t1 = new Thread(sp1);
Thread t2 = new Thread(sp2);
t1.start();
t2.start();
Thread.sleep(3500);
System.out.println("Final Value with Synchronized *******=" + so.getObj());
// Start with Lock
LockProcessor lp1 = at.new LockProcessor(so, "Three", 1500);
LockProcessor lp2 = at.new LockProcessor(so, "Four", 1);
Thread t11 = new Thread(lp1);
Thread t22 = new Thread(lp2);
t11.start();
t22.start();
Thread.sleep(3500);
System.out.println("Final Value with reentrant*******=" + so.getObj());
}
private class SharedObject {
private String obj;
public String getObj() {
return obj;
}
public void setObj(String obj) {
this.obj = obj;
}
}
private class SyncProcessor implements Runnable {
private SharedObject toProcess;
private String val;
private int sleep;
public SyncProcessor(SharedObject toProcess, String val, int sleep) {
this.toProcess = toProcess;
this.val = val;
this.sleep = sleep;
}
@Override
public void run() {
synchronized (toProcess) {
System.out.println("Start write" + val);
try {
Thread.sleep(sleep);
toProcess.setObj(val);
} catch (Exception ex) {
}
System.out.println("End write" + val);
}
}
}
private class LockProcessor implements Runnable {
private SharedObject toProcess;
private String val;
private int sleep;
private Lock lock = new ReentrantLock();
public LockProcessor(SharedObject toProcess, String val, int sleep) {
this.toProcess = toProcess;
this.val = val;
this.sleep = sleep;
}
@Override
public void run() {
lock.lock();
System.out.println("Start write" + val);
try {
Thread.sleep(sleep);
toProcess.setObj(val);
} catch (Exception ex) {
}
System.out.println("End write" + val);
lock.unlock();
}
}
}
Analysis of Example: In the above example there are two processors SyncProcessor and LockProcessor and both process the passed SharedObject.
When we run this prgram we get the following result.
The differene between processors are that one is using synchronized block whereas other is using Lock mechanism.
Difference: When we are using synchronized block then we are taking lock on SharedObject's object and we can define it in synchronized but when using Lock interface we are taking lock on LockProcessor's object.
We should be careful during replacement of synchronized block with Lock.
ReentrantLock object can not take lock on specified object.
Example:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class AtomicTest {
public static void main(String[] args) throws Exception {
AtomicTest at = new AtomicTest();
SharedObject so = at.new SharedObject();
SyncProcessor sp1 = at.new SyncProcessor(so, "One", 1500);
SyncProcessor sp2 = at.new SyncProcessor(so, "Two", 1);
Thread t1 = new Thread(sp1);
Thread t2 = new Thread(sp2);
t1.start();
t2.start();
Thread.sleep(3500);
System.out.println("Final Value with Synchronized *******=" + so.getObj());
// Start with Lock
LockProcessor lp1 = at.new LockProcessor(so, "Three", 1500);
LockProcessor lp2 = at.new LockProcessor(so, "Four", 1);
Thread t11 = new Thread(lp1);
Thread t22 = new Thread(lp2);
t11.start();
t22.start();
Thread.sleep(3500);
System.out.println("Final Value with reentrant*******=" + so.getObj());
}
private class SharedObject {
private String obj;
public String getObj() {
return obj;
}
public void setObj(String obj) {
this.obj = obj;
}
}
private class SyncProcessor implements Runnable {
private SharedObject toProcess;
private String val;
private int sleep;
public SyncProcessor(SharedObject toProcess, String val, int sleep) {
this.toProcess = toProcess;
this.val = val;
this.sleep = sleep;
}
@Override
public void run() {
synchronized (toProcess) {
System.out.println("Start write" + val);
try {
Thread.sleep(sleep);
toProcess.setObj(val);
} catch (Exception ex) {
}
System.out.println("End write" + val);
}
}
}
private class LockProcessor implements Runnable {
private SharedObject toProcess;
private String val;
private int sleep;
private Lock lock = new ReentrantLock();
public LockProcessor(SharedObject toProcess, String val, int sleep) {
this.toProcess = toProcess;
this.val = val;
this.sleep = sleep;
}
@Override
public void run() {
lock.lock();
System.out.println("Start write" + val);
try {
Thread.sleep(sleep);
toProcess.setObj(val);
} catch (Exception ex) {
}
System.out.println("End write" + val);
lock.unlock();
}
}
}
Analysis of Example: In the above example there are two processors SyncProcessor and LockProcessor and both process the passed SharedObject.
When we run this prgram we get the following result.
Start writeOne
End writeOne
Start writeTwo
End writeTwo
Final Value with Synchronized *******=Two
Start writeThree
Start writeFour
End writeFour
End writeThree
Final Value with reentrant*******=Three
The differene between processors are that one is using synchronized block whereas other is using Lock mechanism.
Difference: When we are using synchronized block then we are taking lock on SharedObject's object and we can define it in synchronized but when using Lock interface we are taking lock on LockProcessor's object.
We should be careful during replacement of synchronized block with Lock.
Why Use ThreadLocal Variable in Java
java.lang.ThreadLocal class can be used when you want that each thread should have it's own copy of values in a shared object and in multithreaded environment.
Example:
import java.util.HashMap;
import java.util.Map;
public class Test
{
private static Map<String, String> map = new HashMap<String, String>();
private static ThreadLocal<Map<String, String>> tmap = new
ThreadLocal<Map<String, String>>()
{
protected java.util.Map<String, String> initialValue()
{
return new HashMap<String, String>();
}
};
private static int cnt = 1;
public static void main(String[] st)
throws Exception
{
new ThreadRun().start();
Thread.sleep(1000);
System.out.println("**************************************");
cnt++;
new ThreadRun().start();
}
private static class ThreadRun
extends Thread
{
@Override
public void run()
{
tmap.get().put("One" + cnt, "ThreadLocal" + cnt);
map.put("One" + cnt, "OneValue" + cnt);
System.out.println(cnt + "....ThreadLocal=" + tmap.get());
System.out.println(cnt + "....RunOne=" + map);
}
}
}
Analysis of Example: Above example is having three shared variables(they are static) one is map (type of HashMap) and other is tmap(type of ThreadLocal) and intger counter cnt.
One static class ThreadRun which will process the shared objects map and tmap. When we run this program get the following result.
When we ran the first thread it put values in map and tmap. But when second thread runs values are being put in map object whereas values in tmap is being put in different HashMap so for map same HashMap is used for all thread but if we use ThreadLocal then there will be separate HahMap objects for separate threads because when a new thread tries to get the values from ThreadLocal variable it's initialValues method is called which returns new HashMap for each new thread, so tmap is having only one value whereas map is having two values.
initialValue method of ThreadLocal provides the initial value for a Thread. If the accessing Thread is not having any associated Map then a new HahMap will be returned otherwise stored HashMap will be returned.
Use: One use for this is to distribute JDBC Connection objects to different request Threads because JDBC Connections should not be shared among different request processing.
Example:
import java.util.HashMap;
import java.util.Map;
public class Test
{
private static Map<String, String> map = new HashMap<String, String>();
private static ThreadLocal<Map<String, String>> tmap = new
ThreadLocal<Map<String, String>>()
{
protected java.util.Map<String, String> initialValue()
{
return new HashMap<String, String>();
}
};
private static int cnt = 1;
public static void main(String[] st)
throws Exception
{
new ThreadRun().start();
Thread.sleep(1000);
System.out.println("**************************************");
cnt++;
new ThreadRun().start();
}
private static class ThreadRun
extends Thread
{
@Override
public void run()
{
tmap.get().put("One" + cnt, "ThreadLocal" + cnt);
map.put("One" + cnt, "OneValue" + cnt);
System.out.println(cnt + "....ThreadLocal=" + tmap.get());
System.out.println(cnt + "....RunOne=" + map);
}
}
}
Analysis of Example: Above example is having three shared variables(they are static) one is map (type of HashMap) and other is tmap(type of ThreadLocal) and intger counter cnt.
One static class ThreadRun which will process the shared objects map and tmap. When we run this program get the following result.
1....ThreadLocal={One1=ThreadLocal1}
1....RunOne={One1=OneValue1}
**************************************
2....ThreadLocal={One2=ThreadLocal2}
2....RunOne={One2=OneValue2, One1=OneValue1}
When we ran the first thread it put values in map and tmap. But when second thread runs values are being put in map object whereas values in tmap is being put in different HashMap so for map same HashMap is used for all thread but if we use ThreadLocal then there will be separate HahMap objects for separate threads because when a new thread tries to get the values from ThreadLocal variable it's initialValues method is called which returns new HashMap for each new thread, so tmap is having only one value whereas map is having two values.
initialValue method of ThreadLocal provides the initial value for a Thread. If the accessing Thread is not having any associated Map then a new HahMap will be returned otherwise stored HashMap will be returned.
Use: One use for this is to distribute JDBC Connection objects to different request Threads because JDBC Connections should not be shared among different request processing.
Subscribe to:
Posts (Atom)