I considered the increment decrement approach, but it creates a race
condition with the counter.  Having many different threads/tasks
trying to grab the lock at the same time  could increment the number
above one, even when no one has the lock because there is still a
period of time between the increment() and decrement().  Remember,
these are RPC calls going over the network.  If any part of that
interaction is slow, there will be even longer periods between the +1
and -1.  I think this method errs on the side of accidentally locking
when there isn't a lock.  The only negatives I see would apply to any
lock that's implemented in a cache.


On Dec 15, 8:23 am, Simon <[email protected]> wrote:
> Hi,
>
> I think the following should work with the following caveats:
> - there's a small danger that if the server blows up before it
> releases the lock, that no threads would be able to update your cache,
> but since it's only a cache of data. This is easily mitigated by
> introducing a task which periodically resets the lock.
> - I still believe that there's the possibility that separate instances
> will get a non-updated object, even if you use the locking, since I'm
> assuming it takes x-amount of time for the changes in MemCache to
> propagate throughout the instances.  I may be wrong in this assumption
> however.
>
> Anyway, your code would go something like:
>
> boolean lockAcquired = false;
>
> try {
>     lockAcquired = acquireLock();
>     doStuff();} finally {
>
>     if (lockAcquired) {
>         releaseLock();
>     }
>
> }
>
> With the locking code being:
>
>     public static boolean acquireLock() {
>
>         boolean lockAcquired = true;
>         try {
>             while (increment() != 1) {
>                 decrement();
>                 Thread.sleep(500);
>             }
>         } catch (Throwable t) {
>             // Log error
>             lockAcquired = false;
>         }
>
>         return lockAcquired;
>     }
>
>     public static void releaseLock() {
>         decrement();
>     }
>
>     private static void decrement() {
>         MemcacheServiceFactory.getMemcacheService().increment("LOCK",
> -1, 0L);
>     }
>
>     private static Long increment() {
>         return
> MemcacheServiceFactory.getMemcacheService().increment("LOCK", 1, 0L);
>     }
>
> On Dec 14, 9:56 pm, Jay Young <[email protected]> wrote:
>
>
>
>
>
>
>
> > Grr.  Just noticed another issue.  The cache item that you get the
> > index is not the same item as the lock, so really you need two
> > different cache items, one to make sure you have a unique value for
> > the lock, and the lock itself.  The code above is correct, you just
> > need different keys for the first two cache reads.
>
> > If you can generate a guaranteed-unique name (maybe the thread ID +
> > time?), you can drop the first cache item and use that as the lock
> > value.  This would also prevent the issue with the code above if the
> > lockIndex item is ever evicted and re-read at the same time (thus
> > returning 0 for both), or if it overflows the long.
>
> > (I honestly don't know if this is iron-clad, but intuitively it seems
> > like it would work with only very minor edge cases.)
>
> > On Dec 14, 4:08 pm, Andrei Cosmin Fifiiþã <[email protected]>
> > wrote:
>
> > > Hmmmm, super...
> > > I was thinking of smth like (val mod 2) == 0/1 (true/false), but the lock
> > > reading wasn't safe.
> > > Thanks!
>
> > > On 14 December 2010 20:57, Jay Young <[email protected]> wrote:
>
> > > > Except return lockIndex should just be return true.
>
> > > > --
> > > > You received this message because you are subscribed to the Google 
> > > > Groups
> > > > "Google App Engine for Java" group.
> > > > To post to this group, send email to
> > > > [email protected].
> > > > To unsubscribe from this group, send email to
> > > > [email protected]<google-appengine-java%2B
> > > >  [email protected]>
> > > > .
> > > > For more options, visit this group at
> > > >http://groups.google.com/group/google-appengine-java?hl=en.

-- 
You received this message because you are subscribed to the Google Groups 
"Google App Engine for Java" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/google-appengine-java?hl=en.

Reply via email to