Return-Path: Delivered-To: apmail-hbase-dev-archive@www.apache.org Received: (qmail 69351 invoked from network); 26 May 2010 04:17:10 -0000 Received: from unknown (HELO mail.apache.org) (140.211.11.3) by 140.211.11.9 with SMTP; 26 May 2010 04:17:10 -0000 Received: (qmail 81990 invoked by uid 500); 26 May 2010 04:17:10 -0000 Delivered-To: apmail-hbase-dev-archive@hbase.apache.org Received: (qmail 81898 invoked by uid 500); 26 May 2010 04:17:10 -0000 Mailing-List: contact dev-help@hbase.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@hbase.apache.org Delivered-To: mailing list dev@hbase.apache.org Received: (qmail 81885 invoked by uid 99); 26 May 2010 04:17:09 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 26 May 2010 04:17:09 +0000 X-ASF-Spam-Status: No, hits=-0.0 required=10.0 tests=SPF_PASS X-Spam-Check-By: apache.org Received-SPF: pass (athena.apache.org: local policy) Received: from [203.89.202.182] (HELO postoffice2.aconex.com) (203.89.202.182) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 26 May 2010 04:17:02 +0000 X-ASG-Debug-ID: 1274847399-70f602910000-pO6Xgt X-Barracuda-URL: http://postoffice2.aconex.com:8000/cgi-bin/mark.cgi Received: from postoffice.aconex.com (localhost [127.0.0.1]) by postoffice2.aconex.com (Spam & Virus Firewall) with ESMTP id 180A96B5F22 for ; Wed, 26 May 2010 14:16:39 +1000 (EST) Received: from postoffice.aconex.com (postoffice.yarra.acx [192.168.102.1]) by postoffice2.aconex.com with ESMTP id sEBw5hDIuMroD0T2 for ; Wed, 26 May 2010 14:16:39 +1000 (EST) X-Barracuda-Envelope-From: cowan@aconex.com Received: from gatekeeper.aconex.com (gatekeeper.yarra.acx [192.168.102.10]) by postoffice.aconex.com (Postfix) with ESMTP id 9FA51A50235 for ; Wed, 26 May 2010 14:13:15 +1000 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) by gatekeeper.aconex.com (Postfix) with ESMTP id B628C488753 for ; Wed, 26 May 2010 14:16:39 +1000 (EST) X-Virus-Scanned: amavisd-new at aconex.com Received: from gatekeeper.aconex.com ([127.0.0.1]) by localhost (gatekeeper.aconex.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id tIszbBcMwzU4 for ; Wed, 26 May 2010 14:16:35 +1000 (EST) Received: from [10.1.1.111] (123-2-173-191.static.dsl.dodo.com.au [123.2.173.191]) by gatekeeper.aconex.com (Postfix) with ESMTP id BC8EB488752 for ; Wed, 26 May 2010 14:16:34 +1000 (EST) Message-ID: <4BFCA09C.1010801@aconex.com> Date: Wed, 26 May 2010 14:16:28 +1000 From: Paul Cowan User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; en-GB; rv:1.9.1.9) Gecko/20100317 Thunderbird/3.0.4 MIME-Version: 1.0 To: dev@hbase.apache.org X-ASG-Orig-Subj: Re: Review Request: HBASE-2578 Subject: Re: Review Request: HBASE-2578 References: <20100526011535.21168.39066@ip-10-250-10-165.ec2.internal> <20100526031513.21168.77683@ip-10-250-10-165.ec2.internal> <4BFC99F5.3060006@aconex.com> In-Reply-To: Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-Barracuda-Connect: postoffice.yarra.acx[192.168.102.1] X-Barracuda-Start-Time: 1274847400 X-Barracuda-Virus-Scanned: by Aconex Staff Email Spam Firewall at aconex.com On 26/05/2010 1:54 PM, Ryan Rawson wrote: > Thanks for that salient comment. Perhaps someone can give us the right > pattern for no lock Singleton initialization. There are really only two things which complicate thread-safe singletons: 1) Having a setter, so you can replace the singleton 2) Lazy initialization. The only excuse for this is having a horribly-expensive-to-create singleton, which may not even be used, and you don't under any circumstances wish to create it unless it's needed. This is hard to get right, and 99% of the time you should just instantiate it at class initializion time and forget it. In this case, 1) applies, but 2) doesn't; luckily 1) is a lot easier to get right than 2). Simplest 'correct' patterns are: Basic Singleton (neither #1 nor #2 apply) ------------------------------------------- public class Thing { private static final Thing INSTANCE = new AwesomeThing(); public Thing get() { return INSTANCE; } } this is easy, simple, performant (no synchronization or locking at all) and 100% thread-safe (as long as INSTANCE is final). Replacable Singleton (#1 applies) ------------------------------------------- public class Thing { private static volatile Thing instance = new AwesomeThing(); // Note: volatile public Thing get() { return instance; } public void set(Thing newThing) { this.instance = newThing; } } Nearly as easy, all that's required here is a volatile instance which gives you the correct happens-before relationship. Lazy-Initialized Singleton (#2 applies) ------------------------------------------- Avoid if possible, but if not, one of: Synchronized Getter: public synchronized Thing get() { if (instance == null) { instance = new AwesomeThing(); } return instance; } Double-checked locking (ONLY works in Java 5+) public Thing get() { if (instance == null) { synchronized (ThingHolder.class) { if (instance == null) { // Yes, you need this instance = new AwesomeThing(); } } } return instance; Use java classloading locking guarantees + holder class (see: Effective Java) class ThingHolder { private static final Thing INSTANCE = new AwesomeThing(); } class Thing { public Thing getThing() { return ThingHolder.instance; } } Lazy-Initialized Settable Singleton (#1 + #2 apply) ------------------------------------------- You almost certainly don't need this. You think you do, but you don't. Find a better way. :) Hope that helps. Cheers, Paul