+ Start a Discussion
LVSLVS 

Lock on Apex class variable

I'm new to Apex; though not to programming as such.

 

I have run into a situation where 2 AJAX requests to a controller method (action function) are running simulataneously and their flow of control depends on a shared variable (class level instance variable). Am facing a classic Race Condition - value set by one is not read by another.

 

Is there a way I can put a lock or mutex on a variable to make sure this doesn't happen?

 

Thanks in advance!

bob_buzzardbob_buzzard

I think you'd need to store this kind of information at the database level rather than the class level.  Each ajax request will run in its own transaction, so anything you try to do at the class level won't be shared across transactions. You might try querying the lock back FOR UPDATE, as that should block other transactions from updating the data.  However, the docs aren't overly clear about what happens if you try to query the data while another transaction has a FOR UPDATE.

LVSLVS

thanks Bob. A DML operation can be hard because there's already a latency due to a web service callout that's happening AND multiple users might be using the same page at the time which increases complexity.

 

Here are other ideas I had, but not sure if it can be done in SF:

 

  • Using custom settings instead of DB records
  • Storing the shared value in user session - if that's possible

Let me know what you think.

 

Thanks,

LVS

bob_buzzardbob_buzzard

I don't think you'll be able to get at the user session on the server - this is something that has eluded me in the past.

 

Custom settings would avoid SOQL queries, but you'd still need to use DML to update them to indicate you had grabbed a lock.  I think you'd still have a race condition there though, as you'd need to stop two users writing to the same custom setting. 

 

This is a bit of a tough one - I'd be inclined to see if you can serialise the events from the browser, as at least you have visibility and control of the request flow from there.

LVSLVS

My original problem was AJAX calls being made out of order. In each AJAX call, I send the current UNIX timestamp (calculated before invoking in Javascript) and here's what I'm trying to do. Long lastTimeStamp is init to 0:

 

if(lastTimeStamp < incomingCallTimestamp) // first call, or new call
            lastTimeStamp = incomingCallTimestamp;
        else
            return; // out of date call, exit

//rest of the code goes here..

 

It is the lastTimeStamp variable that I need to get a lock on.

James KentJames Kent

If anyone stumbles onto this, I wrote an blog post on how I solved this:

Obtaining a lock / mutex when executing Apex on Salesforce.com