Singleton Pattern: Part 3 Double Checked Locking

  • user warning: Table './jtekpool/cache_filter' is marked as crashed and last (automatic?) repair failed query: SELECT data, created, headers, expire FROM cache_filter WHERE cid = '4:1b475350524ff0949b0f812ba7acf587' in /home/content/j/e/u/jeugeorge/html/includes/database.mysql.inc on line 172.
  • user warning: Table './jtekpool/cache_filter' is marked as crashed and last (automatic?) repair failed query: LOCK TABLES cache_filter WRITE in /home/content/j/e/u/jeugeorge/html/includes/database.mysql.inc on line 172.
  • user warning: Table './jtekpool/cache_filter' is marked as crashed and last (automatic?) repair failed query: UPDATE cache_filter SET data = '<p><strong>Singleton Pattern: Part 3 Double Checked Locking</strong></p>\n<p>In the <a href=\"http://www.tekpool.com/?p=27\">last post</a> on Singleton Patterns, We looked into a thread safe mechanism to create singleton objects. The concept works well enough for most systems. However, when this becomes a hot section (heavily accessed) in your code, we will begin to hit performance problems. Here\'s why: Lets say we have a high performant system, with 50-100 threads working around like magic, sharing tasks and running as fast as possible. Lets say that all the threads hit this hot section very often. This will result in the hot section being a real bottle neck, synchronizing and slowing down all the threads. Every thread enters this critical section and blocks every other thread from using this section. But is this really required? The \'clever\' double locking system \'tries\' to fix this problem.</p>\n<p>Instead of locking down the critical section and blocking all the threads, this technique gives a chance for the threads to asynchronously check, whether or not it needs to enter this section in the first place. If it does (when instance != null), it then locks the section and proceeds in a normal thread safe manner where it does the second check. So the name, Double Checked Locking.</p>\n<p><code></p>\n<pre>\n class Singleton\n {\n private:\n static Singleton instance;\n\n\n protected Singleton()\n {\n }\n\n public static Singleton CreateInstance()\n {\n\n if(instance == null) //first check\n {\n // Use a mutex locking mechanism\n // that suits your system\n LockCriticalSection();\n if (instance == null) //second check\n {\n instance = new Singleton();\n }\n UnLockCriticalSection();\n }\n return instance;\n }\n}\n\n</pre><p></code></p>\n<p>Note: If you are using Java to implement this, beware that there are issues in Java\'s memory model that prevent this technique from working correctly. This issue is however, fixed. So make sure you have the latest JDK if you plan to use this in your code. In a later post, I will go over the bug in JDK, more specifically in Java\'s memory model that causes this problem.</p>\n', created = 1369509685, expire = 1369596085, headers = '' WHERE cid = '4:1b475350524ff0949b0f812ba7acf587' in /home/content/j/e/u/jeugeorge/html/includes/database.mysql.inc on line 172.
  • user warning: Table './jtekpool/cache_filter' is marked as crashed and last (automatic?) repair failed query: SELECT data, created, headers, expire FROM cache_filter WHERE cid = '1:ec7d31d4a409105bb9212e9f33f92cd0' in /home/content/j/e/u/jeugeorge/html/includes/database.mysql.inc on line 172.
  • user warning: Table './jtekpool/cache_filter' is marked as crashed and last (automatic?) repair failed query: LOCK TABLES cache_filter WRITE in /home/content/j/e/u/jeugeorge/html/includes/database.mysql.inc on line 172.
  • user warning: Table './jtekpool/cache_filter' is marked as crashed and last (automatic?) repair failed query: UPDATE cache_filter SET data = '<p>Double-Check Lock Pattern (DCLP) used to be considered pretty clever, and was asked about in C++ interviews. However, it can\'t be implemented in a reliable, portable (compilers, platforms) way, even if you use the volatile keyword six ways \'til Sunday, and may behave differently on uniprocessor or multiprocessor architectures. Thus, it shouldn\'t be used, and probably shouldn\'t be asked about in interviews. The key is for callers to know that accessing the singleton is expensive and writing appropriate code. Also, try to avoid \"singletonitis\". Not everything needs to be a singleton in the first place. Prefer explicit object semantics to the \"jump wire\" approach - if you have a method called \"doStuff()\" that makes use of a singleton... printer, for example, I\'d much rather see \"doStuff(const Printer&amp;);\" in the header file. This article published jointly by Scott Meyers and Andrei Alexandrescu goes a long way to explaining the dangers of DCLP better than I can: http://www.aristeia.com/Papers/DDJ<em>Jul</em>Aug<em>2004</em>revised.pdf</p>\n', created = 1369509685, expire = 1369596085, headers = '' WHERE cid = '1:ec7d31d4a409105bb9212e9f33f92cd0' in /home/content/j/e/u/jeugeorge/html/includes/database.mysql.inc on line 172.
  • user warning: Table './jtekpool/cache_filter' is marked as crashed and last (automatic?) repair failed query: SELECT data, created, headers, expire FROM cache_filter WHERE cid = '3:05a779c55b13c5bf231fbb667991aab1' in /home/content/j/e/u/jeugeorge/html/includes/database.mysql.inc on line 172.
  • user warning: Table './jtekpool/cache_filter' is marked as crashed and last (automatic?) repair failed query: LOCK TABLES cache_filter WRITE in /home/content/j/e/u/jeugeorge/html/includes/database.mysql.inc on line 172.
  • user warning: Table './jtekpool/cache_filter' is marked as crashed and last (automatic?) repair failed query: UPDATE cache_filter SET data = '<div>\n<a href=\"http://www.tekpool.com/forums\">Tekpool Forums</a>\n</div>\n', created = 1369509685, expire = 1369596085, headers = '' WHERE cid = '3:05a779c55b13c5bf231fbb667991aab1' in /home/content/j/e/u/jeugeorge/html/includes/database.mysql.inc on line 172.
  • user warning: Table './jtekpool/cache_filter' is marked as crashed and last (automatic?) repair failed query: SELECT data, created, headers, expire FROM cache_filter WHERE cid = '3:6d2e93175e73578556e23cdf79916e14' in /home/content/j/e/u/jeugeorge/html/includes/database.mysql.inc on line 172.
  • user warning: Table './jtekpool/cache_filter' is marked as crashed and last (automatic?) repair failed query: LOCK TABLES cache_filter WRITE in /home/content/j/e/u/jeugeorge/html/includes/database.mysql.inc on line 172.
  • user warning: Table './jtekpool/cache_filter' is marked as crashed and last (automatic?) repair failed query: UPDATE cache_filter SET data = '<script type=\"text/javascript\"> \n <!-- \n microsoft_adunitid=\"1098\"; \n microsoft_adunit_width=\"160\"; \n microsoft_adunit_height=\"600\"; \n //--> \n </script><script type=\"text/javascript\" src=\"https://adsyndication.msn.com/delivery/getads.js\" ></script>', created = 1369509685, expire = 1369596085, headers = '' WHERE cid = '3:6d2e93175e73578556e23cdf79916e14' in /home/content/j/e/u/jeugeorge/html/includes/database.mysql.inc on line 172.

Singleton Pattern: Part 3 Double Checked Locking

In the last post on Singleton Patterns, We looked into a thread safe mechanism to create singleton objects. The concept works well enough for most systems. However, when this becomes a hot section (heavily accessed) in your code, we will begin to hit performance problems. Here's why: Lets say we have a high performant system, with 50-100 threads working around like magic, sharing tasks and running as fast as possible. Lets say that all the threads hit this hot section very often. This will result in the hot section being a real bottle neck, synchronizing and slowing down all the threads. Every thread enters this critical section and blocks every other thread from using this section. But is this really required? The 'clever' double locking system 'tries' to fix this problem.

Instead of locking down the critical section and blocking all the threads, this technique gives a chance for the threads to asynchronously check, whether or not it needs to enter this section in the first place. If it does (when instance != null), it then locks the section and proceeds in a normal thread safe manner where it does the second check. So the name, Double Checked Locking.

  class Singleton
  {
    private:
    static Singleton instance;


    protected Singleton()
    {
    }

    public static Singleton CreateInstance()
    {

      if(instance == null) //first check
      {
          // Use a mutex locking mechanism
          //  that suits your system
          LockCriticalSection();
          if (instance == null) //second check
          {
            instance = new Singleton();
          }
          UnLockCriticalSection();
       }
       return instance;
   }
}

Note: If you are using Java to implement this, beware that there are issues in Java's memory model that prevent this technique from working correctly. This issue is however, fixed. So make sure you have the latest JDK if you plan to use this in your code. In a later post, I will go over the bug in JDK, more specifically in Java's memory model that causes this problem.

Comments

Double-Check Lock Pattern

Double-Check Lock Pattern (DCLP) used to be considered pretty clever, and was asked about in C++ interviews. However, it can't be implemented in a reliable, portable (compilers, platforms) way, even if you use the volatile keyword six ways 'til Sunday, and may behave differently on uniprocessor or multiprocessor architectures. Thus, it shouldn't be used, and probably shouldn't be asked about in interviews. The key is for callers to know that accessing the singleton is expensive and writing appropriate code. Also, try to avoid "singletonitis". Not everything needs to be a singleton in the first place. Prefer explicit object semantics to the "jump wire" approach - if you have a method called "doStuff()" that makes use of a singleton... printer, for example, I'd much rather see "doStuff(const Printer&);" in the header file. This article published jointly by Scott Meyers and Andrei Alexandrescu goes a long way to explaining the dangers of DCLP better than I can: http://www.aristeia.com/Papers/DDJJulAug2004revised.pdf