diff --git a/.travis.php.ini b/.travis.php.ini
new file mode 100644
index 0000000..5121d16
--- /dev/null
+++ b/.travis.php.ini
@@ -0,0 +1,2 @@
+extension=memcache.so
+extension=memcached.so
diff --git a/.travis.yml b/.travis.yml
index 3465114..9e0fdc6 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -17,8 +17,7 @@ services:
  - redis-server
 
 before_script:
- - ./tests/travis/memcache-setup.sh
- - ./tests/travis/memcached-setup.sh
+ - if [[ "$TRAVIS_PHP_VERSION" != "hhvm" ]]; then cat .travis.php.ini >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini ; echo "Loading additional config for version $TRAVIS_PHP_VERSION" ; fi
  - ./tests/travis/composer-setup.sh
  - ./tests/travis/mysql-setup.sh
 
diff --git a/src/NinjaMutex/Lock/LockExpirationInterface.php b/src/NinjaMutex/Lock/LockExpirationInterface.php
new file mode 100644
index 0000000..d169acb
--- /dev/null
+++ b/src/NinjaMutex/Lock/LockExpirationInterface.php
@@ -0,0 +1,29 @@
+<?php
+/**
+ * This file is part of ninja-mutex.
+ *
+ * (C) Kamil Dziedzic <arvenil@klecza.pl>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace NinjaMutex\Lock;
+
+/**
+ * Lock implementor
+ *
+ * @author Kamil Dziedzic <arvenil@klecza.pl>
+ */
+interface LockExpirationInterface
+{
+    /**
+     * @param int $expiration Expiration time of the lock in seconds.
+     */
+    public function setExpiration($expiration);
+
+    /**
+     * @param  string $name
+     * @return bool
+     */
+    public function clearLock($name);
+}
diff --git a/src/NinjaMutex/Lock/MemcacheLock.php b/src/NinjaMutex/Lock/MemcacheLock.php
index f6bf998..b6b2f53 100644
--- a/src/NinjaMutex/Lock/MemcacheLock.php
+++ b/src/NinjaMutex/Lock/MemcacheLock.php
@@ -16,13 +16,107 @@
  *
  * @author Kamil Dziedzic <arvenil@klecza.pl>
  */
-class MemcacheLock extends MemcacheLockAbstract
+class MemcacheLock extends LockAbstract implements LockExpirationInterface
 {
+    /**
+     * Maximum expiration time in seconds (30 days)
+     * http://php.net/manual/en/memcache.add.php
+     */
+    const MAX_EXPIRATION = 2592000;
+
+    /**
+     * Memcache connection
+     *
+     * @var Memcache
+     */
+    protected $memcache;
+
+    /**
+     * @var int Expiration time of the lock in seconds
+     */
+    protected $expiration = 0;
+
     /**
      * @param Memcache $memcache
      */
     public function __construct(Memcache $memcache)
     {
-        parent::__construct($memcache);
+        parent::__construct();
+
+        $this->memcache = $memcache;
+    }
+
+    /**
+     * @param int $expiration Expiration time of the lock in seconds. If it's equal to zero (default), the lock will never expire.
+     *                        Max 2592000s (30 days), if greater it will be capped to 2592000 without throwing an error.
+     *                        WARNING: Using value higher than 0 may lead to race conditions. If you set too low expiration time
+     *                        e.g. 30s and critical section will run for 31s another process will gain lock at the same time,
+     *                        leading to unpredicted behaviour. Use with caution.
+     */
+    public function setExpiration($expiration)
+    {
+        if ($expiration > static::MAX_EXPIRATION) {
+            $expiration = static::MAX_EXPIRATION;
+        }
+        $this->expiration = $expiration;
+    }
+
+    /**
+     * Clear lock without releasing it
+     * Do not use this method unless you know what you do
+     *
+     * @param  string $name name of lock
+     * @return bool
+     */
+    public function clearLock($name)
+    {
+        if (!isset($this->locks[$name])) {
+            return false;
+        }
+
+        unset($this->locks[$name]);
+        return true;
+    }
+
+    /**
+     * @param  string $name name of lock
+     * @param  bool   $blocking
+     * @return bool
+     */
+    protected function getLock($name, $blocking)
+    {
+        if (!$this->memcache->add($name, serialize($this->getLockInformation()), 0, $this->expiration)) {
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Release lock
+     *
+     * @param  string $name name of lock
+     * @return bool
+     */
+    public function releaseLock($name)
+    {
+        if (isset($this->locks[$name]) && $this->memcache->delete($name)) {
+            unset($this->locks[$name]);
+
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Check if lock is locked
+     *
+     * @param  string $name name of lock
+     * @return bool
+     */
+    public function isLocked($name)
+    {
+        return false !== $this->memcache->get($name);
     }
 }
diff --git a/src/NinjaMutex/Lock/MemcacheLockAbstract.php b/src/NinjaMutex/Lock/MemcacheLockAbstract.php
deleted file mode 100644
index 88a6a20..0000000
--- a/src/NinjaMutex/Lock/MemcacheLockAbstract.php
+++ /dev/null
@@ -1,77 +0,0 @@
-<?php
-/**
- * This file is part of ninja-mutex.
- *
- * (C) Kamil Dziedzic <arvenil@klecza.pl>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-namespace NinjaMutex\Lock;
-
-/**
- * Abstract for lock implementor using Memcache or Memcached
- *
- * @author Kamil Dziedzic <arvenil@klecza.pl>
- */
-abstract class MemcacheLockAbstract extends LockAbstract
-{
-    /**
-     * Memcache connection
-     *
-     * @var \Memcached|\Memcache
-     */
-    protected $memcache;
-
-    /**
-     * @param \Memcached|\Memcache $memcache
-     */
-    public function __construct($memcache)
-    {
-        parent::__construct();
-
-        $this->memcache = $memcache;
-    }
-
-    /**
-     * @param  string $name
-     * @param  bool   $blocking
-     * @return bool
-     */
-    protected function getLock($name, $blocking)
-    {
-        if (!$this->memcache->add($name, serialize($this->getLockInformation()))) {
-            return false;
-        }
-
-        return true;
-    }
-
-    /**
-     * Release lock
-     *
-     * @param  string $name name of lock
-     * @return bool
-     */
-    public function releaseLock($name)
-    {
-        if (isset($this->locks[$name]) && $this->memcache->delete($name)) {
-            unset($this->locks[$name]);
-
-            return true;
-        }
-
-        return false;
-    }
-
-    /**
-     * Check if lock is locked
-     *
-     * @param  string $name name of lock
-     * @return bool
-     */
-    public function isLocked($name)
-    {
-        return false !== $this->memcache->get($name);
-    }
-}
diff --git a/src/NinjaMutex/Lock/MemcachedLock.php b/src/NinjaMutex/Lock/MemcachedLock.php
index 639b449..88a2051 100644
--- a/src/NinjaMutex/Lock/MemcachedLock.php
+++ b/src/NinjaMutex/Lock/MemcachedLock.php
@@ -16,13 +16,108 @@
  *
  * @author Kamil Dziedzic <arvenil@klecza.pl>
  */
-class MemcachedLock extends MemcacheLockAbstract
+class MemcachedLock extends LockAbstract implements LockExpirationInterface
 {
+    /**
+     * Maximum expiration time in seconds (30 days)
+     * http://php.net/manual/en/memcached.add.php
+     */
+    const MAX_EXPIRATION = 2592000;
+
+    /**
+     * Memcache connection
+     *
+     * @var Memcached
+     */
+    protected $memcached;
+
+    /**
+     * @var int Expiration time of the lock in seconds
+     */
+    protected $expiration = 0;
+
     /**
      * @param Memcached $memcached
      */
-    public function __construct(Memcached $memcached)
+    public function __construct($memcached)
+    {
+        parent::__construct();
+
+        $this->memcached = $memcached;
+    }
+
+    /**
+     * @param int $expiration Expiration time of the lock in seconds. If it's equal to zero (default), the lock will never expire.
+     *                        Max 2592000s (30 days), if greater it will be capped to 2592000 without throwing an error.
+     *                        WARNING: Using value higher than 0 may lead to race conditions. If you set too low expiration time
+     *                        e.g. 30s and critical section will run for 31s another process will gain lock at the same time,
+     *                        leading to unpredicted behaviour. Use with caution.
+     */
+    public function setExpiration($expiration)
+    {
+        if ($expiration > static::MAX_EXPIRATION) {
+            $expiration = static::MAX_EXPIRATION;
+        }
+        $this->expiration = $expiration;
+    }
+
+    /**
+     * Clear lock without releasing it
+     * Do not use this method unless you know what you do
+     *
+     * @param  string $name name of lock
+     * @return bool
+     */
+    public function clearLock($name)
     {
-        parent::__construct($memcached);
+        if (!isset($this->locks[$name])) {
+            return false;
+        }
+
+        unset($this->locks[$name]);
+        return true;
+    }
+
+    /**
+     * @param  string $name name of lock
+     * @param  bool   $blocking
+     * @return bool
+     */
+    protected function getLock($name, $blocking)
+    {
+        if (!$this->memcached->add($name, serialize($this->getLockInformation()), $this->expiration)) {
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Release lock
+     *
+     * @param  string $name name of lock
+     * @return bool
+     */
+    public function releaseLock($name)
+    {
+        if (isset($this->locks[$name]) && $this->memcached->delete($name)) {
+            unset($this->locks[$name]);
+
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Check if lock is locked
+     *
+     * @param  string $name name of lock
+     * @return bool
+     */
+    public function isLocked($name)
+    {
+        return false !== $this->memcached->get($name);
     }
 }
+
diff --git a/tests/NinjaMutex/AbstractTest.php b/tests/NinjaMutex/AbstractTest.php
index 3bb0ec5..9b94711 100644
--- a/tests/NinjaMutex/AbstractTest.php
+++ b/tests/NinjaMutex/AbstractTest.php
@@ -9,12 +9,12 @@
  */
 namespace NinjaMutex;
 
-use Memcache;
-use Memcached;
 use NinjaMutex\Lock\FlockLock;
 use NinjaMutex\Lock\MemcacheLock;
 use NinjaMutex\Lock\MemcachedLock;
 use NinjaMutex\Lock\MySqlLock;
+use NinjaMutex\Lock\Fabric\MemcacheLockFabric;
+use NinjaMutex\Lock\Fabric\MemcachedLockFabric;
 use NinjaMutex\Mock\MockMemcache;
 use NinjaMutex\Mock\MockMemcached;
 use NinjaMutex\Mock\MockPredisClient;
@@ -48,8 +48,14 @@ public function tearDown()
         rmdir('/tmp/mutex/');
     }
 
+    /**
+     * @return array
+     */
     public function lockImplementorProvider()
     {
+        $memcacheLockFabric = new MemcacheLockFabric();
+        $memcachedLockFabric = new MemcachedLockFabric();
+
         $data = array(
             // Just mocks
             $this->provideFlockMockLock(),
@@ -59,8 +65,8 @@ public function lockImplementorProvider()
             $this->providePredisRedisMockLock(),
             // Real locks
             $this->provideFlockLock(),
-            $this->provideMemcacheLock(),
-            $this->provideMemcachedLock(),
+            array($memcacheLockFabric->create()),
+            array($memcachedLockFabric->create()),
             $this->provideMysqlLock(),
             $this->providePredisRedisLock(),
         );
@@ -68,6 +74,9 @@ public function lockImplementorProvider()
         return $data;
     }
 
+    /**
+     * @return array
+     */
     public function lockImplementorWithBackendProvider()
     {
         $data = array(
@@ -80,6 +89,22 @@ public function lockImplementorWithBackendProvider()
         return $data;
     }
 
+    /**
+     * @return array
+     */
+    public function lockFabricWithExpirationProvider()
+    {
+        $memcacheLockFabric = new MemcacheLockFabric();
+        $memcachedLockFabric = new MemcachedLockFabric();
+
+        $data = array(
+            array($memcacheLockFabric),
+            array($memcachedLockFabric),
+        );
+
+        return $data;
+    }
+
     /**
      * @return array
      */
@@ -126,28 +151,6 @@ protected function providePredisRedisMockLock()
         return array(new PredisRedisLock($predisMock), $predisMock);
     }
 
-    /**
-     * @return array
-     */
-    protected function provideMemcacheLock()
-    {
-        $memcache = new Memcache();
-        $memcache->connect('127.0.0.1', 11211);
-
-        return array(new MemcacheLock($memcache));
-    }
-
-    /**
-     * @return array
-     */
-    protected function provideMemcachedLock()
-    {
-        $memcached = new Memcached();
-        $memcached->addServer('127.0.0.1', 11211);
-
-        return array(new MemcachedLock($memcached));
-    }
-
     /**
      * @return array
      */
diff --git a/tests/NinjaMutex/Lock/Fabric/LockFabricWithExpirationInterface.php b/tests/NinjaMutex/Lock/Fabric/LockFabricWithExpirationInterface.php
new file mode 100644
index 0000000..2ba96f2
--- /dev/null
+++ b/tests/NinjaMutex/Lock/Fabric/LockFabricWithExpirationInterface.php
@@ -0,0 +1,25 @@
+<?php
+/**
+ * This file is part of ninja-mutex.
+ *
+ * (C) Kamil Dziedzic <arvenil@klecza.pl>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace NinjaMutex\Lock\Fabric;
+use NinjaMutex\Lock\LockInterface;
+use NinjaMutex\Lock\LockExpirationInterface;
+
+/**
+ * Lock Fabric interface
+ *
+ * @author Kamil Dziedzic <arvenil@klecza.pl>
+ */
+interface LockFabricWithExpirationInterface
+{
+    /**
+     * @return LockInterface|LockExpirationInterface
+     */
+    public function create();
+}
diff --git a/tests/NinjaMutex/Lock/Fabric/MemcacheLockFabric.php b/tests/NinjaMutex/Lock/Fabric/MemcacheLockFabric.php
new file mode 100644
index 0000000..1ceea5d
--- /dev/null
+++ b/tests/NinjaMutex/Lock/Fabric/MemcacheLockFabric.php
@@ -0,0 +1,25 @@
+<?php
+/**
+ * This file is part of ninja-mutex.
+ *
+ * (C) Kamil Dziedzic <arvenil@klecza.pl>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace NinjaMutex\Lock\Fabric;
+
+use Memcache;
+use NinjaMutex\Lock\MemcacheLock;
+
+class MemcacheLockFabric implements LockFabricWithExpirationInterface {
+    /**
+     * @return MemcacheLock
+     */
+    public function create() {
+        $memcache = new Memcache();
+        $memcache->connect('127.0.0.1', 11211);
+
+        return new MemcacheLock($memcache);
+    }
+}
diff --git a/tests/NinjaMutex/Lock/Fabric/MemcachedLockFabric.php b/tests/NinjaMutex/Lock/Fabric/MemcachedLockFabric.php
new file mode 100644
index 0000000..11772c0
--- /dev/null
+++ b/tests/NinjaMutex/Lock/Fabric/MemcachedLockFabric.php
@@ -0,0 +1,25 @@
+<?php
+/**
+ * This file is part of ninja-mutex.
+ *
+ * (C) Kamil Dziedzic <arvenil@klecza.pl>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace NinjaMutex\Lock\Fabric;
+
+use Memcached;
+use NinjaMutex\Lock\MemcachedLock;
+
+class MemcachedLockFabric implements LockFabricWithExpirationInterface {
+    /**
+     * @return MemcachedLock
+     */
+    public function create() {
+        $memcached = new Memcached();
+        $memcached->addServer('127.0.0.1', 11211);
+
+        return new MemcachedLock($memcached);
+    }
+}
diff --git a/tests/NinjaMutex/Lock/LockTest.php b/tests/NinjaMutex/Lock/LockTest.php
index 5291449..5249c20 100644
--- a/tests/NinjaMutex/Lock/LockTest.php
+++ b/tests/NinjaMutex/Lock/LockTest.php
@@ -10,6 +10,7 @@
 namespace NinjaMutex\Lock;
 
 use NinjaMutex\AbstractTest;
+use NinjaMutex\Lock\Fabric\LockFabricWithExpirationInterface;
 use NinjaMutex\Mock\PermanentServiceInterface;
 use NinjaMutex\UnrecoverableMutexException;
 
@@ -127,6 +128,8 @@ public function testIfLockIsReleasedAfterLockImplementorIsDestroyed(LockInterfac
 
     /**
      * @issue https://github.com/arvenil/ninja-mutex/pull/4
+     * It's not working for hhvm, see below link to understand limitation
+     * https://github.com/facebook/hhvm/blob/af329776c9f740cc1c8c4791f673ba5aa49042ce/hphp/doc/inconsistencies#L40-L45
      *
      * @dataProvider lockImplementorWithBackendProvider
      * @param LockInterface             $lockImplementor
@@ -160,4 +163,36 @@ public function testIfLockDestructorThrowsWhenBackendIsUnavailable(LockInterface
         $this->fail('An expected exception has not been raised.');
     }
 
+    /**
+     * @issue https://github.com/arvenil/ninja-mutex/issues/12
+     * @medium Timeout for test increased to ~5s http://stackoverflow.com/a/10535787/916440
+     *
+     * @dataProvider lockFabricWithExpirationProvider
+     * @param LockFabricWithExpirationInterface $lockFabricWithExpiration
+     */
+    public function testExpiration(LockFabricWithExpirationInterface $lockFabricWithExpiration)
+    {
+        $expiration = 2; // in seconds
+        $name = "lockWithExpiration_" . uniqid();
+        $lockImplementor = $lockFabricWithExpiration->create();
+        $lockImplementorWithExpiration = $lockFabricWithExpiration->create();
+        $lockImplementorWithExpiration->setExpiration($expiration);
+
+        // Aquire lock on implementor with lock expiration
+        $this->assertTrue($lockImplementorWithExpiration->acquireLock($name, 0));
+        // We hope code was fast enough so $expiration time didn't pass yet and lock still should be held
+        $this->assertFalse($lockImplementor->acquireLock($name, 0));
+
+        // Let's wait for lock to expire
+        sleep($expiration);
+
+        // Let's try again to lock
+        $this->assertTrue($lockImplementor->acquireLock($name, 0));
+
+        // Cleanup
+        $this->assertTrue($lockImplementor->releaseLock($name, 0));
+        // Expired lock is unusable, we need to clean it's lock state or otherwise
+        // it will invoke in __destruct Exception (php*) or Fatal Error (hhvm)
+        $this->assertTrue($lockImplementorWithExpiration->clearLock($name, 0));
+    }
 }
diff --git a/tests/NinjaMutex/Mock/MockMemcached.php b/tests/NinjaMutex/Mock/MockMemcached.php
index 77f6f27..b6c02d7 100644
--- a/tests/NinjaMutex/Mock/MockMemcached.php
+++ b/tests/NinjaMutex/Mock/MockMemcached.php
@@ -9,14 +9,13 @@
  */
 namespace NinjaMutex\Mock;
 
-use Memcached;
 
 /**
  * Mock memcached to mimic mutex functionality
  *
  * @author Kamil Dziedzic <arvenil@klecza.pl>
  */
-class MockMemcached extends Memcached implements PermanentServiceInterface
+class MockMemcached implements PermanentServiceInterface
 {
     /**
      * @var string[]
@@ -34,12 +33,13 @@ public function __construct()
     }
 
     /**
-     * @param  string $key
-     * @param  mixed  $value
-     * @param  null   $expiration
+     * @param  string   $key
+     * @param  mixed    $value
+     * @param  int|null $expiration
+     * @param  null     $udf_flags
      * @return bool
      */
-    public function add($key, $value, $expiration = null)
+    public function add($key, $value, $expiration = null, &$udf_flags = null)
     {
         if (!$this->available) {
             return false;
@@ -58,9 +58,10 @@ public function add($key, $value, $expiration = null)
      * @param  string            $key
      * @param  null              $cache_cb
      * @param  null              $cas_token
+     * @param  null              $udf_flags
      * @return bool|mixed|string
      */
-    public function get($key, $cache_cb = null, &$cas_token = null)
+    public function get($key, $cache_cb = null, &$cas_token = null, &$udf_flags = null)
     {
         if (!$this->available) {
             return false;
diff --git a/tests/travis/composer-setup.sh b/tests/travis/composer-setup.sh
index 10a6a39..08d5476 100755
--- a/tests/travis/composer-setup.sh
+++ b/tests/travis/composer-setup.sh
@@ -1,3 +1,3 @@
 #!/bin/sh
 
-wget -nc http://getcomposer.org/composer.phar && php composer.phar install --dev --prefer-source
+wget -nc http://getcomposer.org/composer.phar && php composer.phar install --prefer-source
diff --git a/tests/travis/memcache-setup.sh b/tests/travis/memcache-setup.sh
deleted file mode 100755
index b0e419f..0000000
--- a/tests/travis/memcache-setup.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/sh
-
-install_memcache() {
-    if [ $(expr "${TRAVIS_PHP_VERSION}" "!=" "hhvm") -eq 1 ] && [ $(expr "${TRAVIS_PHP_VERSION}" "!=" "hhvm-nightly") -eq 1 ]; then
-        echo "extension=memcache.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
-    fi
-
-    return $?
-}
-
-install_memcache > ~/memcache.log || ( echo "=== MEMCACHE INSTALL FAILED ==="; cat ~/memcache.log; exit 1 )
diff --git a/tests/travis/memcached-setup.sh b/tests/travis/memcached-setup.sh
deleted file mode 100755
index 14c9905..0000000
--- a/tests/travis/memcached-setup.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/sh
-
-install_memcached() {
-    if [ $(expr "${TRAVIS_PHP_VERSION}" "!=" "hhvm") -eq 1 ] && [ $(expr "${TRAVIS_PHP_VERSION}" "!=" "hhvm-nightly") -eq 1 ]; then
-        echo "extension=memcached.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
-    fi
-
-    return $?
-}
-
-install_memcached > ~/memcached.log || ( echo "=== MEMCACHED INSTALL FAILED ==="; cat ~/memcached.log; exit 1 )