curator-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From dragonsinth <>
Subject [GitHub] curator pull request: CURATOR-151: SharedValue/SharedCount API upd...
Date Thu, 09 Oct 2014 17:11:29 GMT
Github user dragonsinth commented on a diff in the pull request:
    --- Diff: curator-recipes/src/main/java/org/apache/curator/framework/recipes/shared/
    @@ -184,6 +178,25 @@ public boolean trySetValue(VersionedValue<byte[]> newValue)
throws Exception
             return false;
    +    private void updateValue(int version, byte[] bytes)
    +    {
    +        while (true)
    +        {
    +            VersionedValue<byte[]> current = currentValue.get();
    +            if (current.getVersion() >= version)
    +            {
    +                // A newer version was concurrently set.
    +                return;
    +            }
    +            if ( currentValue.compareAndSet(current, new VersionedValue<byte[]>(version,
bytes)) )
    +            {
    +                // Successfully set.
    +                return;
    +            }
    +            // Lost a race, retry.
    +        }
    +    }
    --- End diff --
    Let me elaborate a little on the race condition this solves.
    Imagine the current value is (1, A) you have one thread calling trySetValue(B) another
calling trySetValue(C) at the same time.  Imagine thread 1 succeeds in making the server call
first and updating the server value to (2, B) and immediately afterwards thread 2 succeeds
in calling the server and updating the server value to (3, C).   But to due to thread scheduling
or what have you, both threads actually enter updateValue() at the same time.  How do we ensure
that the correct value ends up in currentValue when both threads exit updateValue so that
the client has the correct server state?
    That's what the compare-and-set loop solves.  Imagine both threads enter the loop and
initially read current as (1, A).  Then they both try to compare and set (1, A) to either
(2, B) or (3, C).  Only one of them can win the race.  If (2, B) gets set, then the first
thread will return and the second thread will try again, and this time succeed in updating
(2, B) -> (3, C).  If (3, C) gets set then the second thread will return, and the first
thread will try again.  But this time it will exit out because it will see that someone else
already set a higher-versioned value.
    This actually solves several potential races, between threads calling setValue/trySetValue
at the same time and also any threads that could be calling readValue() at the same time (watcher,
failed trySetValue(), or even the start() call).

If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at or file a JIRA ticket
with INFRA.

View raw message