[concurrency-interest] Object finalization

Gregg Wonderly gregg at cytetech.com
Sat May 26 10:52:41 EDT 2012


On 5/15/2012 6:45 PM, Boehm, Hans wrote:
>> From: Gregg Wonderly
>>
>> On 5/15/2012 8:15 AM, David M. Lloyd wrote:
>>> I've given up on finalization for native resources for just this
>> reason; instead
>>> I use refcounting. It's not great because there's a CAS on entry+exit
>> but I find
>>> that I can also use the same trick to replace locking in many cases
>> so I'm
>>> hoping that it'll even out in the benchmarks. I almost have myself
>> convinced
>>> that it will scale better than the finalizer option. We shall see.
>>
>> I've done this in a lot of other places myself too.  It just simplifies
>> so many
>> things to have dependable, accurate life cycles.
>>
>> Gregg
>
> It seems to me that, depending on the context, that may be trading one can of worms for another.
> Possibly a bigger one.
>
> To me, there are two distinct kinds of cleanup actions:
>
> 1) Logically synchronous; the programmer knows exactly where it's happening, and can make
> sure that the locks acquired by the cleanup code aren't acquired in the wrong order with
> respect to the calling context, etc.  C++ destructors are good at this.  Explicit cleanup
> calls often aren't too bad.  Finalizers are terrible.  It seems to me that this case usually
> doesn't even need reference counting, though occasionally it might.  And that may be a perfectly
> good use for reference counting.
>
> 2) Logically asynchronous.  We want it to be cleaned up anytime before we run out of the resource,
> whenever that may be.  This is what happens when an assignment drops the last reference to a
> large data structure containing library-defined objects which I don't understand, and have
> no business understanding.  Finalizers and java.lang.ref are potentially tolerable at this,
> with some fixes.  Traditional reference counting with synchronous resource reclamation
> is terrible at it (at least in the absence of transactional memory).  C++ destructors have
> the same problem.  The problem is that a completely innocuous looking call, performing a
> reference-counted assignment, may end up acquiring a huge collection of locks I don't know
> about, making it essentially impossible to reliably avoid deadlocks.  (This is essentially identical
> to the JDK 1.0.2 finalization bug misdescribed as a language design bug as the first
> item in http://www.cs.arizona.edu/projects/sumatra/hallofshame/ )  The problem can be avoided
> by queuing cleanups to be run later in a separate thread, just like finalizers.
>
> It also seems to me that using reference counting for (2) has a tendency to infect lots of things
> with reference counting, and may largely make the GC redundant.  Once we do that, we've solved a
> problem that was solvable with perhaps a 1% optimization cost by adding huge overhead to every
> pointer assignment.  (Not to mention garbage cycles.)

I have to do this for remote resources where one VM is using something on 
another VM.  Jini remote invocation, requires an exported endpoint.  These 
endpoints need to be released, when the remote end no longer needs them.  A 
leasing mechanism is the only way to manage this issue, and so I use the lease 
object as the triggered "release" to unexport the endpoint and unbind/close the 
associated socket.

Gregg Wonderly


More information about the Concurrency-interest mailing list