Consider:

(def as (lazy-seq (cons 1 bs)))
(def bs (lazy-seq (cons 2 cs)))
;; ...
(def zs (lazy-seq (cons 26 as)))

Suppose you start two threads concurrently. The first forces 'as' and
the second forces 'zs'. If the timing is just right, this can result
in a deadlock:

// LazySeq.java

final synchronized Object sval(){
        if(fn != null)
                {
                try
                        {
                        sv = fn.invoke();
                        fn = null;
                        }
                catch(Exception e)
                        {
                        throw new RuntimeException(e);
                        }
                }
        if(sv != null)
                return sv;
        return s;
}

final synchronized public ISeq seq(){
        sval();
        if(sv != null)
                {
                Object ls = sv;
                sv = null;
                while(ls instanceof LazySeq)
                        {
                        ls = ((LazySeq)ls).sval();
                        }
                s = RT.seq(ls);
                }
        return s;
}

For this sort of reason (as well as the general overhead of locking),
GHC and other compilers for lazy languages only approximately
implement call-by-need: if two threads force an unevaluated thunk
almost simultaneously, they will both evaluate the thunk, and the
first to successfully complete the CAS at the end wins.

This is an excellent implementation strategy in a pure language.
However, in Clojure, it's common to use lazy sequences for side
effects, and evaluating the same thunk multiple times would be very
bad.

I'm not sure what of the best compromise. You could use a
non-synchronized wrapper around seq that checks a volatile variable
(maybe fn itself) to check for multiple evaluation and, in that case,
throw an error. That would amount to deadlock detection.

-Per

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to