On 10/6/07, Jerome Louvel <[EMAIL PROTECTED]> wrote:
>
> I have made the following changes to Guard in SVN 1.0 branch:
> - secrets is now a ConcurrentHashMap instance
> - getSecrets() lazily instantiates the secrets field in a synchronized
> block:


Unfortunately, unless *all* access to the secrets field is done inside
"synchronized (this) {...}" -- including all read access -- this code is
still not correct. I notice that you expose a setSecrets method in 1.1 --
since you're exposing the map itself with getSecrets, there is no need for
this method; it's not clear what its behavior should be in the presence of
concurrent access to the secrets field.

I think it would be better to make secrets final and not expose setSecrets
-- or if you are already committed to exposing it, implement it as something
like

public void setSecrets(Map<String, char[]> secrets) {
    this.secrets.clear();
    this.secrets.putAll(secrets);
}

Interleaved calls to setSecrets might not behave the way you expect -- but
you probably shouldn't be making concurrent calls to setSecrets anyway.


    public Map<String, char[]> getSecrets() {
>                 if (this.secrets == null) {
>                         synchronized (this) {
>                                 if (this.secrets == null) {
>                                         this.secrets = new
> ConcurrentHashMap<String, char[]>();
>                                 }
>                         }
>                 }
>
>                 return this.secrets;
>     }


This is known as the double-checked locking
idiom<http://www.cs.umd.edu/%7Epugh/java/memoryModel/DoubleCheckedLocking.html>,
and it is broken. Don't use it.


In addition, the getSecrets() method in SVN trunk (future 1.1) returns a
> ConcurrentMap instance instead of just Map.


Cool.



> Also the "scheme" and "realm" properties have setters in 1.1, so no reason
> to mark them final.


But in that case they need to be properly synchronized. In this case, you
could make the fields volatile. The other way is to make sure that they are
accessed only while holding a synch lock (the same lock each time). Leaving
them non-final is not correct.

--Tim Peierls

Reply via email to