Reputation: 1670
In my project we are using restful webservices with spring framework, when I call the same request concurrently the property of the object is overriden by one another.
Below is my code.
@Service("testService")
@Scope(value ="prototype")
public class TestServiceImpl extends DefaultServiceBuilder {
public void test() {
process();
System.err.println(tranLog.getTxnId());
}
}
public class DefaultServiceBuilder {
protected TransactionLog tranLog;
public void process() {
tranLog = new TransactionLog();
Random r = new Random();
String rid = r.nextInt(40000)+"";
tranLog.setTxnid(rid);
setTranLog(tranLog);
}
public TransactionLog getTranLog() {
return tranLog;
}
public void setTranLog(TransactionLog tranLog) {
this.tranLog = tranLog;
}
}
public class TransactionLog {
private String txnId;
public void setTxnId(String txnId) {
this.txnId = txnId;
}
public String getTxnId() {
return txnId;
}
}
I am calling the below request with 2 thread parallel.
My expected input is
123456
242422
But the output is
242422
242422
Why the TransactionLog object value is overriding eventhough i gave scope prototype. How to access the Transalog object safely?
Any help will be greatly Appreciated!!!!
Upvotes: 1
Views: 502
Reputation: 969
Class name TransactionLog implies that evety instance of TransactionLog, writed to variable tranLog will be used only in one thread.
If it right, then read further:
In very good book "Java Concurrency in Practice" described one good pattern of thread synchronization:
Thread Confinement
Accessing shared, mutable data requires using synchronization; one way to avoid this requirement is to not share. If data is only accessed from a single thread, no synchronization is needed. This technique, thread confinement, is one of the simplest ways to achieve thread safety. When an object is confined to a thread, such usage is automatically thread-safe even if the confined object itself is not [CPJ 2.3.2].
Make field tranLog just local variable
final TransactionLog tranLog = new TransactionLog();
If you use it in other function, for instance subProcess2:
private void subProcess2() {
tranLog.doSometthing();
}
Add tranLog to function parameters:
private void subProcess2(TransactionLog tranLog) {
tranLog.doSometthing();
}
And pass tranLog when calling subProcess2.
Upvotes: 1
Reputation: 31417
You could synchronize your code, by synchronizing below line of code
protected static TransactionLog tranLog;
public static synchronized void process() {
Random r = new Random();
tranLog = new TransactionLog();
String rid = r.nextInt(40000)+"";
tranLog.setTxnid(rid);
}
Making static synchronized
will allow only one thread at any given time.
Upvotes: 1