hasha
hasha

Reputation: 294

Synchronized block accessed by two threads

I have a synchronized method that is being called from a controller method. When two request access this only one should go through and other should be blocked until first is finished.

But when the incoming requests are fast, this is actually returning same accountId to two different requests, which is not intended.

Please help me understand how do I synchronize this getNextAccount() call so that it only return one account to one request.

Method in AccService.java

private final Object lockObject = new Object();
@Transactional(propagation = Propagation.REQUIRES_NEW)
public Long getNextAccount(String hostport) {
    synchronized (lockObject) {

        Long acc = null;
        try {
            AccountFetch dtls = getAccount();
            if (dtls != null) {
                acc = dtls.getAccId();

                //Set IN_PROGRESS 
                dtls.setStatus("Progress");
                dtls.saveAndFlush(dtls);
                return acc;
            } else {
                log.info("No More Accounts to Process");
            }
        } catch (Exception e) {

            e.getStackTrace();
        }
        return acc;
    }
}

@Autowired
private AccService accSevice;
@GET
@Path("/accprocess")
@Produces(MediaType.APPLICATION_JSON)
public AccountFetch getAccId(@QueryParam("currentHost") final String currentHost,
        @QueryParam("currentPort") final String currentPort) {
    AccountFetch dtls = new AccountFetch();
    try {
        Long batchId = accSevice. getNextAccount(currentHost+"#"+currentPort);
        if (accId != null) {
            dtls.setAccId(String.valueOf(accId));
        } else {
            dtls.setAccId(BLANK_STRING);
        }
    } catch (Exception e) {
        log.error("Exception while getting accId : " + e.getMessage());
    }
    return dtls;
}

public AccountFetch getAccount(){...}

Upvotes: 0

Views: 57

Answers (1)

Stephen C
Stephen C

Reputation: 719679

A synchronized block will only give you mutual exclusion if the threads are on the same host, and if they are locking using the same lock object.

Based on what you originally wrote in your question, it seems that one or both of these preconditions is not satisfied. If (as it now transpires) there is only one host processing these requests, then we must consider the other possibility; i.e. that there multiple instances of the AccService object processing requests.

It is also possible that synchronization is working, and the problem is somewhere else. For example, getAccount() could be returning the same account on successive calls.


Basically, there are too many parts of your code-base that we can't see. This means that we can only theorize as to what is causing the problem. If every thing was done correctly; i.e.

  • there is only one host,
  • all threads are sharing the same lock object,
  • getAccount() is implemented correctly, and
  • nothing else updates the account state used by getAccount without proper synchronization,

then the code you have shown us would work.

If you need more help, an MCVE is probably required.

Upvotes: 1

Related Questions