I am using the following code. I am not able to achieve synchronization. As per me String pool concept should have worked here.
I want to know the reason behind the problem, not the alternatives to it.
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class SynchronizationBug {
private static Map<String,Date> concurrentMap=new ConcurrentHashMap();
public static void start(String processId) throws InterruptedException{
final String lock="log"+processId;
synchronized (lock) {
if(concurrentMap.containsKey(processId)) {
System.out.println("Process is already working and started at "+concurrentMap.get(processId));
return;
}
concurrentMap.put(processId,new Date());
}
}
public static void main(String[] args) throws InterruptedException {
// System.out.println(isPrime(10));
final String pId="p1";
Thread t1=new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
try {
start(pId);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
Thread t2=new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
try {
start(pId);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
t1.start();
t2.start();
t1.join();
t2.join();
for (String s:concurrentMap.keySet()) {
System.out.println(s+" - "+concurrentMap.get(s));
}
}
}
If I take a lock on processId which is passed as a method parameter, then things are working as expected. What is the reason for this behaviour of Java. I have tested this on Java8 Eclipse IDE.
EDIT: If String pool concept has no relevance then how does the following code work fine.
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class SynchronizationBug {
private static Map<String,Date> concurrentMap=new ConcurrentHashMap();
public static void start(String processId) throws InterruptedException{
final String lock="log"+processId;
synchronized (processId) {
if(concurrentMap.containsKey(processId)) {
System.out.println("Process is already working and started at "+concurrentMap.get(processId));
return;
}
concurrentMap.put(processId,new Date());
}
}
public static void main(String[] args) throws InterruptedException {
// System.out.println(isPrime(10));
final String pId1="p1";
final String pId2="p1";
Thread t1=new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
try {
start(pId1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
Thread t2=new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
try {
start(pId2);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
t1.start();
t2.start();
t1.join();
t2.join();
for (String s:concurrentMap.keySet()) {
System.out.println(s+" - "+concurrentMap.get(s));
}
}
}
Here I am passing two different string objects with same value.Due to their same reference in the pool the locking is working fine . Please correct me....