diff --git a/includes/Drupal/Lock/DatabaseLockBackend.php b/includes/Drupal/Lock/DatabaseLockBackend.php
index e69de29..0944d10 100644
--- a/includes/Drupal/Lock/DatabaseLockBackend.php
+++ b/includes/Drupal/Lock/DatabaseLockBackend.php
@@ -0,0 +1,97 @@
+<?php
+
+namespace Drupal\Lock;
+
+use \PDOException;
+
+class DatabaseLockBackend extends LockBackendAbstract {
+
+  public function acquire($name, $timeout = 30.0) {
+    // Insure that the timeout is at least 1 ms.
+    $timeout = max($timeout, 0.001);
+    $expire = microtime(TRUE) + $timeout;
+    if (isset($this->locks[$name])) {
+      // Try to extend the expiration of a lock we already acquired.
+      $success = (bool) db_update('semaphore')
+        ->fields(array('expire' => $expire))
+        ->condition('name', $name)
+        ->condition('value', $this->getLockId())
+        ->execute();
+      if (!$success) {
+        // The lock was broken.
+        unset($this->locks[$name]);
+      }
+      return $success;
+    }
+    else {
+      // Optimistically try to acquire the lock, then retry once if it fails.
+      // The first time through the loop cannot be a retry.
+      $retry = FALSE;
+      // We always want to do this code at least once.
+      do {
+        try {
+          db_insert('semaphore')
+            ->fields(array(
+              'name' => $name,
+              'value' => $this->getLockId(),
+              'expire' => $expire,
+            ))
+            ->execute();
+          // We track all acquired locks in the global variable.
+          $this->locks[$name] = TRUE;
+          // We never need to try again.
+          $retry = FALSE;
+        }
+        catch (PDOException $e) {
+          // Suppress the error. If this is our first pass through the loop,
+          // then $retry is FALSE. In this case, the insert must have failed
+          // meaning some other request acquired the lock but did not release it.
+          // We decide whether to retry by checking lock_may_be_available()
+          // Since this will break the lock in case it is expired.
+          $retry = $retry ? FALSE : $this->lockMayBeAvailable($name);
+        }
+        // We only retry in case the first attempt failed, but we then broke
+        // an expired lock.
+      } while ($retry);
+    }
+    return isset($this->locks[$name]);
+  }
+
+  public function lockMayBeAvailable($name) {
+    $lock = db_query('SELECT expire, value FROM {semaphore} WHERE name = :name', array(':name' => $name))->fetchAssoc();
+    if (!$lock) {
+      return TRUE;
+    }
+    $expire = (float) $lock['expire'];
+    $now = microtime(TRUE);
+    if ($now > $expire) {
+      // We check two conditions to prevent a race condition where another
+      // request acquired the lock and set a new expire time. We add a small
+      // number to $expire to avoid errors with float to string conversion.
+      return (bool) db_delete('semaphore')
+        ->condition('name', $name)
+        ->condition('value', $lock['value'])
+        ->condition('expire', 0.0001 + $expire, '<=')
+        ->execute();
+    }
+    return FALSE;
+  }
+
+  public function release($name) {
+    unset($this->lock[$name]);
+    db_delete('semaphore')
+      ->condition('name', $name)
+      ->condition('value', $this->getLockId())
+      ->execute();
+  }
+
+  public function releaseAll($lock_id = NULL) {
+    $this->locks = array();
+    if (empty($lock_id)) {
+      $lock_id = $this->getLockId();
+    }
+    db_delete('semaphore')
+      ->condition('value', $lock_id)
+      ->execute();
+  }
+}
diff --git a/includes/Drupal/Lock/LockBackendAbstract.php b/includes/Drupal/Lock/LockBackendAbstract.php
index e69de29..9269f20 100644
--- a/includes/Drupal/Lock/LockBackendAbstract.php
+++ b/includes/Drupal/Lock/LockBackendAbstract.php
@@ -0,0 +1,64 @@
+<?php
+
+namespace Drupal\Lock;
+
+abstract class LockBackendAbstract implements LockBackendInterface {
+  /**
+   * Current page lock token identifier.
+   * 
+   * @var string
+   */
+  protected $lockId;
+
+  /**
+   * Existing locks for this page.
+   * 
+   * @var array
+   */
+  protected $locks = array();
+
+  public function wait($name, $delay = 30) {
+    // Pause the process for short periods between calling
+    // lock_may_be_available(). This prevents hitting the database with constant
+    // database queries while waiting, which could lead to performance issues.
+    // However, if the wait period is too long, there is the potential for a
+    // large number of processes to be blocked waiting for a lock, especially
+    // if the item being rebuilt is commonly requested. To address both of these
+    // concerns, begin waiting for 25ms, then add 25ms to the wait period each
+    // time until it reaches 500ms. After this point polling will continue every
+    // 500ms until $delay is reached.
+
+    // $delay is passed in seconds, but we will be using usleep(), which takes
+    // microseconds as a parameter. Multiply it by 1 million so that all
+    // further numbers are equivalent.
+    $delay = (int) $delay * 1000000;
+
+    // Begin sleeping at 25ms.
+    $sleep = 25000;
+    while ($delay > 0) {
+      // This function should only be called by a request that failed to get a
+      // lock, so we sleep first to give the parallel request a chance to finish
+      // and release the lock.
+      usleep($sleep);
+      // After each sleep, increase the value of $sleep until it reaches
+      // 500ms, to reduce the potential for a lock stampede.
+      $delay = $delay - $sleep;
+      $sleep = min(500000, $sleep + 25000, $delay);
+      if ($this->lockMayBeAvailable($name)) {
+        // No longer need to wait.
+        return FALSE;
+      }
+    }
+    // The caller must still wait longer to get the lock.
+    return TRUE;
+  }
+
+  public function getLockId() {
+    if (!isset($this->lockId)) {
+      $this->lockId = uniqid(mt_rand(), TRUE);
+      // We only register a shutdown function if a lock is used.
+      drupal_register_shutdown_function('lock_release_all', $this->lockId);
+    }
+    return $this->lockId;
+  }
+}
diff --git a/includes/Drupal/Lock/LockBackendInterface.php b/includes/Drupal/Lock/LockBackendInterface.php
index e69de29..445d9c9 100644
--- a/includes/Drupal/Lock/LockBackendInterface.php
+++ b/includes/Drupal/Lock/LockBackendInterface.php
@@ -0,0 +1,60 @@
+<?php
+
+namespace Drupal\Lock;
+
+interface LockBackendInterface {
+  /**
+   * Acquire lock.
+   * 
+   * @param string $name
+   *   Lock name.
+   * @param float $timeout = 30.0
+   *   (optional) Lock lifetime in seconds.
+   * 
+   * @return bool
+   */
+  public function acquire($name, $timeout = 30.0);
+
+  /**
+   * Check if lock is available for acquire.
+   * 
+   * @param string $name
+   *   Lock to acquire.
+   * 
+   * @return bool
+   */
+  public function lockMayBeAvailable($name);
+
+  /**
+   * Wait a short amount of time before a second lock acquire attempt.
+   * 
+   * @param string $name
+   *   Lock name currently being locked.
+   * @param int $delay = 30
+   *   Miliseconds to wait for.
+   */
+  public function wait($name, $delay = 30);
+
+  /**
+   * Release given lock.
+   * 
+   * @param string $name
+   */
+  public function release($name);
+
+  /**
+   * Release all locks for the given lock token identifier.
+   * 
+   * @param string $lockId = NULL
+   *   (optional) If none given, remove all lock from the current page.
+   */
+  public function releaseAll($lock_id = NULL);
+
+  /**
+   * Get the unique page token for locks. Locks will be wipeout at each end of
+   * page request on a token basis.
+   * 
+   * @return string
+   */
+  public function getLockId();
+}
diff --git a/includes/bootstrap.inc b/includes/bootstrap.inc
index 2856529..c6f398b 100644
--- a/includes/bootstrap.inc
+++ b/includes/bootstrap.inc
@@ -2315,8 +2315,7 @@ function _drupal_bootstrap_variables() {
   global $conf;
 
   // Initialize the lock system.
-  require_once DRUPAL_ROOT . '/' . variable_get('lock_inc', 'includes/lock.inc');
-  lock_initialize();
+  require_once DRUPAL_ROOT . '/includes/lock.inc';
 
   // Load variables from the database, but do not overwrite variables set in settings.php.
   $conf = variable_initialize(isset($conf) ? $conf : array());
diff --git a/includes/lock.inc b/includes/lock.inc
index 7dd8db3..3739f27 100644
--- a/includes/lock.inc
+++ b/includes/lock.inc
@@ -61,31 +61,43 @@
  * no code should look for or directly modify a lock in the {semaphore} table).
  */
 
+// FIXME: Temporary manual file inclusion, since no autoloader still has been
+// commited yet to core.
+require_once DRUPAL_ROOT . '/includes/Drupal/Lock/LockBackendInterface.php';
+require_once DRUPAL_ROOT . '/includes/Drupal/Lock/LockBackendAbstract.php';
+require_once DRUPAL_ROOT . '/includes/Drupal/Lock/DatabaseLockBackend.php';
+require_once DRUPAL_ROOT . '/includes/Drupal/Lock/LockToken.php';
+require_once DRUPAL_ROOT . '/includes/Drupal/Lock/LockFactory.php';
+
+use Drupal\Lock\LockBackendInterface;
+use Drupal\Lock\DatabaseLockBackend;
+use Drupal\Lock\LockToken;
+use Drupal\Lock\LockFactory;
+
 /**
- * Initialize the locking system.
+ * Get lock backend.
+ * 
+ * @return Drupal\Lock\LockFactory
  */
-function lock_initialize() {
-  global $locks;
-
-  $locks = array();
+function lock_get_factory() {
+  static $factory;
+  if (!isset($factory)) {
+    $className = variable_get('default_lock_backend', 'Drupal\Lock\DatabaseLockBackend');
+    $factory = new LockFactory(new $className);
+  }
+  return $factory;
 }
 
 /**
- * Helper function to get this request's unique id.
+ * Acquire lock.
+ * 
+ * @param string $name
+ * 
+ * @return LockToken
+ *   LockToken instance in case of success, FALSE else.
  */
-function _lock_id() {
-  // Do not use drupal_static(). This identifier refers to the current
-  // client request, and must not be changed under any circumstances
-  // else the shutdown handler may fail to release our locks.
-  static $lock_id;
-
-  if (!isset($lock_id)) {
-    // Assign a unique id.
-    $lock_id = uniqid(mt_rand(), TRUE);
-    // We only register a shutdown function if a lock is used.
-    drupal_register_shutdown_function('lock_release_all', $lock_id);
-  }
-  return $lock_id;
+function lock($name) {
+  return lock_get_factory()->acquire($name);
 }
 
 /**
@@ -98,89 +110,18 @@ function _lock_id() {
  *
  * @return
  *   TRUE if the lock was acquired, FALSE if it failed.
+ * 
+ * @deprecated
  */
 function lock_acquire($name, $timeout = 30.0) {
-  global $locks;
-
-  // Insure that the timeout is at least 1 ms.
-  $timeout = max($timeout, 0.001);
-  $expire = microtime(TRUE) + $timeout;
-  if (isset($locks[$name])) {
-    // Try to extend the expiration of a lock we already acquired.
-    $success = (bool) db_update('semaphore')
-      ->fields(array('expire' => $expire))
-      ->condition('name', $name)
-      ->condition('value', _lock_id())
-      ->execute();
-    if (!$success) {
-      // The lock was broken.
-      unset($locks[$name]);
-    }
-    return $success;
-  }
-  else {
-    // Optimistically try to acquire the lock, then retry once if it fails.
-    // The first time through the loop cannot be a retry.
-    $retry = FALSE;
-    // We always want to do this code at least once.
-    do {
-      try {
-        db_insert('semaphore')
-          ->fields(array(
-            'name' => $name,
-            'value' => _lock_id(),
-            'expire' => $expire,
-          ))
-          ->execute();
-        // We track all acquired locks in the global variable.
-        $locks[$name] = TRUE;
-        // We never need to try again.
-        $retry = FALSE;
-      }
-      catch (PDOException $e) {
-        // Suppress the error. If this is our first pass through the loop,
-        // then $retry is FALSE. In this case, the insert must have failed
-        // meaning some other request acquired the lock but did not release it.
-        // We decide whether to retry by checking lock_may_be_available()
-        // Since this will break the lock in case it is expired.
-        $retry = $retry ? FALSE : lock_may_be_available($name);
-      }
-      // We only retry in case the first attempt failed, but we then broke
-      // an expired lock.
-    } while ($retry);
-  }
-  return isset($locks[$name]);
-}
-
-/**
- * Check if lock acquired by a different process may be available.
- *
- * If an existing lock has expired, it is removed.
- *
- * @param $name
- *   The name of the lock.
- *
- * @return
- *   TRUE if there is no lock or it was removed, FALSE otherwise.
- */
-function lock_may_be_available($name) {
-  $lock = db_query('SELECT expire, value FROM {semaphore} WHERE name = :name', array(':name' => $name))->fetchAssoc();
-  if (!$lock) {
+  $token = lock_get_factory()->acquire($name);
+  if ($token instanceof LockToken) {
+    // Backward compatibility.
+    $token->disableAutoRelease();
     return TRUE;
+  } else {
+    return FALSE;
   }
-  $expire = (float) $lock['expire'];
-  $now = microtime(TRUE);
-  if ($now > $expire) {
-    // We check two conditions to prevent a race condition where another
-    // request acquired the lock and set a new expire time. We add a small
-    // number to $expire to avoid errors with float to string conversion.
-    return (bool) db_delete('semaphore')
-      ->condition('name', $name)
-      ->condition('value', $lock['value'])
-      ->condition('expire', 0.0001 + $expire, '<=')
-      ->execute();
-  }
-  return FALSE;
 }
 
 /**
@@ -199,41 +140,11 @@ function lock_may_be_available($name) {
  *
  * @return
  *   TRUE if the lock holds, FALSE if it is available.
+ * 
+ * @deprecated
  */
 function lock_wait($name, $delay = 30) {
-  // Pause the process for short periods between calling
-  // lock_may_be_available(). This prevents hitting the database with constant
-  // database queries while waiting, which could lead to performance issues.
-  // However, if the wait period is too long, there is the potential for a
-  // large number of processes to be blocked waiting for a lock, especially
-  // if the item being rebuilt is commonly requested. To address both of these
-  // concerns, begin waiting for 25ms, then add 25ms to the wait period each
-  // time until it reaches 500ms. After this point polling will continue every
-  // 500ms until $delay is reached.
-
-  // $delay is passed in seconds, but we will be using usleep(), which takes
-  // microseconds as a parameter. Multiply it by 1 million so that all
-  // further numbers are equivalent.
-  $delay = (int) $delay * 1000000;
-
-  // Begin sleeping at 25ms.
-  $sleep = 25000;
-  while ($delay > 0) {
-    // This function should only be called by a request that failed to get a
-    // lock, so we sleep first to give the parallel request a chance to finish
-    // and release the lock.
-    usleep($sleep);
-    // After each sleep, increase the value of $sleep until it reaches
-    // 500ms, to reduce the potential for a lock stampede.
-    $delay = $delay - $sleep;
-    $sleep = min(500000, $sleep + 25000, $delay);
-    if (lock_may_be_available($name)) {
-      // No longer need to wait.
-      return FALSE;
-    }
-  }
-  // The caller must still wait longer to get the lock.
-  return TRUE;
+  return lock_get_factory()->getBackend()->wait($name, $delay);
 }
 
 /**
@@ -243,30 +154,20 @@ function lock_wait($name, $delay = 30) {
  *
  * @param $name
  *   The name of the lock.
+ * 
+ * @deprecated
  */
 function lock_release($name) {
-  global $locks;
-
-  unset($locks[$name]);
-  db_delete('semaphore')
-    ->condition('name', $name)
-    ->condition('value', _lock_id())
-    ->execute();
+  lock_get_factory()->getBackend()->release($name);
 }
 
 /**
  * Release all previously acquired locks.
+ * 
+ * @deprecated
  */
 function lock_release_all($lock_id = NULL) {
-  global $locks;
-
-  $locks = array();
-  if (empty($lock_id)) {
-    $lock_id = _lock_id();
-  }
-  db_delete('semaphore')
-    ->condition('value', $lock_id)
-    ->execute();
+  lock_get_factory()->getBackend()->releaseAll($lock_id);
 }
 
 /**
