PHPackages                             m-rubin-itmegastar-com/lock - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. m-rubin-itmegastar-com/lock

ActiveLibrary[Database &amp; ORM](/categories/database)

m-rubin-itmegastar-com/lock
===========================

Mutex library for exclusive code execution.

v2.7.2(6y ago)02WTFPLPHPPHP ~7.0

Since Jul 12Pushed 6y agoCompare

[ Source](https://github.com/m-rubin-itmegastar-com/lock)[ Packagist](https://packagist.org/packages/m-rubin-itmegastar-com/lock)[ Docs](https://github.com/m-rubin-itmegastar-com/lock)[ RSS](/packages/m-rubin-itmegastar-com-lock/feed)WikiDiscussions master Synced today

READMEChangelogDependencies (7)Versions (25)Used By (0)

**[Requirements](#requirements)** | **[Installation](#installation)** | **[Usage](#usage)** | **[License and authors](#license-and-authors)** | **[Donations](#donations)**

php-lock/lock
=============

[](#php-locklock)

[![Latest Stable Version](https://camo.githubusercontent.com/188f3cf697e227aad09a30eb2455a47cdddc99660d0345726a7440ca355fdeaf/68747470733a2f2f706f7365722e707567782e6f72672f6d616c6b757363682f6c6f636b2f76657273696f6e)](https://packagist.org/packages/malkusch/lock)[![Total Downloads](https://camo.githubusercontent.com/0eeb694709214e8e55781d0bcc6717b4731c39ee20da12206215f84b8bf6b963/68747470733a2f2f706f7365722e707567782e6f72672f6d616c6b757363682f6c6f636b2f646f776e6c6f616473)](https://packagist.org/packages/malkusch/lock)[![Latest Unstable Version](https://camo.githubusercontent.com/8efc60bb531f5d29b3ade227d313c435319360d46e22de1508b5664a8c7d82fa/68747470733a2f2f706f7365722e707567782e6f72672f6d616c6b757363682f6c6f636b2f762f756e737461626c65)](//packagist.org/packages/malkusch/lock)[![Build Status](https://camo.githubusercontent.com/ad88cf74259cdd44784704ee07501549fc8fb109dca2f84b577fbe9d4d81bc2c/68747470733a2f2f7472617669732d63692e6f72672f7068702d6c6f636b2f6c6f636b2e7376673f6272616e63683d6d6173746572)](https://travis-ci.org/php-lock/lock)[![License](https://camo.githubusercontent.com/f76812d6322750ceaacd3123611e6e6617195f2bd7dedd0378c0c631fd42504e/68747470733a2f2f706f7365722e707567782e6f72672f6d616c6b757363682f6c6f636b2f6c6963656e7365)](https://packagist.org/packages/malkusch/lock)

This library helps executing critical code in concurrent situations.

php-lock/lock follows semantic versioning. Read more on [semver.org](http://semver.org).

---

Requirements
------------

[](#requirements)

- PHP 7.1 or above
- Optionally [nrk/predis](https://github.com/nrk/predis) to use the Predis locks.
- Optionally the [php-pcntl](http://php.net/manual/en/book.pcntl.php) extension to enable locking with `flock()` without busy waiting in CLI scripts.
- Optionally `flock()`, `ext-redis`, `ext-pdo_mysql`, `ext-pdo_sqlite`, `ext-pdo_pgsql` or `ext-memcached` can be used as a backend for locks. See examples below.
- If `ext-redis` is used for locking and is configured to use igbinary for serialization or lzf for compression, additionally `ext-igbinary` and/or `ext-lzf` have to be installed.

---

Installation
------------

[](#installation)

### Composer

[](#composer)

To use this library through [composer](https://getcomposer.org), run the following terminal command inside your repository's root folder.

```
composer require m_rubin_itmegastar_com/lock
```

Usage
-----

[](#usage)

The package is in the namespace [`m_rubin_itmegastar_com\lock`](http://malkusch.github.io/lock/api/namespace-malkusch.lock.html).

### Mutex

[](#mutex)

The [`malkusch\lock\mutex\Mutex`](https://github.com/php-lock/lock/blob/master/classes/mutex/Mutex.php) class is an abstract class and provides the base API for this library.

#### Mutex::synchronized()

[](#mutexsynchronized)

[`malkusch\lock\mutex\Mutex::synchronized()`](https://github.com/php-lock/lock/blob/master/classes/mutex/Mutex.php#L38) executes code exclusively. This method guarantees that the code is only executed by one process at once. Other processes have to wait until the mutex is available. The critical code may throw an exception, which would release the lock as well.

This method returns whatever is returned to the given callable. The return value is not checked, thus it is up to the user to decide if for example the return value `false` or `null` should be seen as a failed action.

Example:

```
$newBalance = $mutex->synchronized(function () use ($bankAccount, $amount): int {
    $balance = $bankAccount->getBalance();
    $balance -= $amount;
    if ($balance < 0) {
        throw new \DomainException('You have no credit.');
    }
    $bankAccount->setBalance($balance);

    return $balance;
});
```

#### Mutex::check()

[](#mutexcheck)

[`malkusch\lock\mutex\Mutex::check()`](https://github.com/php-lock/lock/blob/master/classes/mutex/Mutex.php#L57) sets a callable, which will be executed when [`malkusch\lock\util\DoubleCheckedLocking::then()`](https://github.com/php-lock/lock/blob/master/classes/util/DoubleCheckedLocking.php#L72) is called, and performs a double-checked locking pattern, where it's return value decides if the lock needs to be acquired and the synchronized code to be executed.

See [https://en.wikipedia.org/wiki/Double-checked\_locking](https://en.wikipedia.org/wiki/Double-checked_locking) for a more detailed explanation of that feature.

If the check's callable returns `false`, no lock will be acquired and the synchronized code will not be executed. In this case the [`malkusch\lock\util\DoubleCheckedLocking::then()`](https://github.com/php-lock/lock/blob/master/classes/util/DoubleCheckedLocking.php#L72) method, will also return `false` to indicate that the check did not pass either before or after acquiring the lock.

In the case where the check's callable returns a value other than `false`, the [`malkusch\lock\util\DoubleCheckedLocking::then()`](https://github.com/php-lock/lock/blob/master/classes/util/DoubleCheckedLocking.php#L72) method, will try to acquire the lock and on success will perform the check again. Only when the check returns something other than `false` a second time, the synchronized code callable, which has been passed to `then()` will be executed. In this case the return value of `then()` will be what ever the given callable returns and thus up to the user to return `false` or `null` to indicate a failed action as this return value will not be checked by the library.

Example:

```
$newBalance = $mutex->check(function () use ($bankAccount, $amount): bool {
    return $bankAccount->getBalance() >= $amount;
})->then(function () use ($bankAccount, $amount): int {
    $balance = $bankAccount->getBalance();
    $balance -= $amount;
    $bankAccount->setBalance($balance);

    return $balance;
});

if (false === $newBalance) {
    if ($balance < 0) {
        throw new \DomainException('You have no credit.');
    }
}
```

### Extracting code result after lock release exception

[](#extracting-code-result-after-lock-release-exception)

Mutex implementations based on [`malkush\lock\mutex\LockMutex`](https://github.com/php-lock/lock/blob/master/classes/mutex/LockMutex.php) will throw [`malkusch\lock\exception\LockReleaseException`](https://github.com/php-lock/lock/blob/master/classes/exception/LockReleaseException.php) in case of lock release problem, but the synchronized code block will be already executed at this point. In order to read the code result (or an exception thrown there), `LockReleaseException` provides methods to extract it.

Example:

```
try {
    // or $mutex->check(...)
    $mutex->synchronized(function () {
        if (someCondition()) {
            throw new \DomainException();
        }

        return "result";
    });
} catch (LockReleaseException $unlock_exception) {
    if ($unlock_exception->getCodeException() !== null) {
        $code_exception = $unlock_exception->getCodeException()
        // do something with the code exception
    } else {
        $code_result = $unlock_exception->getCodeResult();
        // do something with the code result
    }

    // deal with LockReleaseException or propagate it
    throw $unlock_exception;
}
```

### Implementations

[](#implementations)

Because the [`malkusch\lock\mutex\Mutex`](#mutex) class is an abstract class, you can choose from one of the provided implementations or create/extend your own implementation.

- [`CASMutex`](#casmutex)
- [`FlockMutex`](#flockmutex)
- [`MemcachedMutex`](#memcachedmutex)
- [`PHPRedisMutex`](#phpredismutex)
- [`PredisMutex`](#predismutex)
- [`SemaphoreMutex`](#semaphoremutex)
- [`TransactionalMutex`](#transactionalmutex)
- [`MySQLMutex`](#mysqlmutex)
- [`PgAdvisoryLockMutex`](#pgadvisorylockmutex)

#### CASMutex

[](#casmutex)

The **CASMutex** has to be used with a [Compare-and-swap](https://en.wikipedia.org/wiki/Compare-and-swap) operation. This mutex is lock free. It will repeat executing the code until the CAS operation was successful. The code should therefore notify the mutex by calling [`malkusch\lock\mutex\CASMutex::notify()`](https://github.com/php-lock/lock/blob/master/classes/mutex/CASMutex.php#L44).

As the mutex keeps executing the critical code, it must not have any side effects as long as the CAS operation was not successful.

Example:

```
$mutex = new CASMutex();
$mutex->synchronized(function () use ($memcached, $mutex, $amount): void {
    $balance = $memcached->get("balance", null, $casToken);
    $balance -= $amount;
    if (!$memcached->cas($casToken, "balance", $balance)) {
        return;

    }
    $mutex->notify();
});
```

#### FlockMutex

[](#flockmutex)

The **FlockMutex** is a lock implementation based on [`flock()`](http://php.net/manual/en/function.flock.php).

Example:

```
$mutex = new FlockMutex(fopen(__FILE__, "r"));
$mutex->synchronized(function () use ($bankAccount, $amount) {
    $balance = $bankAccount->getBalance();
    $balance -= $amount;
    if ($balance < 0) {
        throw new \DomainException("You have no credit.");

    }
    $bankAccount->setBalance($balance);
});
```

Timeouts are supported as an optional second argument. This uses the `ext-pcntl`extension if possible or busy waiting if not.

#### MemcachedMutex

[](#memcachedmutex)

The **MemcachedMutex**is a spinlock implementation which uses the [`Memcached` API](http://php.net/manual/en/book.memcached.php).

Example:

```
$memcache = new \Memcached();
$memcache->addServer("localhost", 11211);

$mutex = new MemcachedMutex("balance", $memcache);
$mutex->synchronized(function () use ($bankAccount, $amount) {
    $balance = $bankAccount->getBalance();
    $balance -= $amount;
    if ($balance < 0) {
        throw new \DomainException("You have no credit.");

    }
    $bankAccount->setBalance($balance);
});
```

#### PHPRedisMutex

[](#phpredismutex)

The **PHPRedisMutex** is the distributed lock implementation of [RedLock](http://redis.io/topics/distlock)which uses the [`phpredis` extension](https://github.com/phpredis/phpredis).

This implementation requires at least `phpredis-2.2.4`.

If used with a cluster of Redis servers, acquiring and releasing locks will continue to function as long as a majority of the servers still works.

Example:

```
$redis = new Redis();
$redis->connect("localhost");

$mutex = new PHPRedisMutex([$redis], "balance");
$mutex->synchronized(function () use ($bankAccount, $amount) {
    $balance = $bankAccount->getBalance();
    $balance -= $amount;
    if ($balance < 0) {
        throw new \DomainException("You have no credit.");

    }
    $bankAccount->setBalance($balance);
});
```

#### PredisMutex

[](#predismutex)

The **PredisMutex** is the distributed lock implementation of [RedLock](http://redis.io/topics/distlock)which uses the [`Predis` API](https://github.com/nrk/predis).

Example:

```
$redis = new Client("redis://localhost");

$mutex = new PredisMutex([$redis], "balance");
$mutex->synchronized(function () use ($bankAccount, $amount) {
    $balance = $bankAccount->getBalance();
    $balance -= $amount;
    if ($balance < 0) {
        throw new \DomainException("You have no credit.");

    }
    $bankAccount->setBalance($balance);
});
```

#### SemaphoreMutex

[](#semaphoremutex)

The **SemaphoreMutex**is a lock implementation based on [Semaphore](http://php.net/manual/en/ref.sem.php).

Example:

```
$semaphore = sem_get(ftok(__FILE__, "a"));
$mutex     = new SemaphoreMutex($semaphore);
$mutex->synchronized(function () use ($bankAccount, $amount) {
    $balance = $bankAccount->getBalance();
    $balance -= $amount;
    if ($balance < 0) {
        throw new \DomainException("You have no credit.");

    }
    $bankAccount->setBalance($balance);
});
```

#### TransactionalMutex

[](#transactionalmutex)

The **TransactionalMutex**delegates the serialization to the DBS. The exclusive code is executed within a transaction. It's up to you to set the correct transaction isolation level. However if the transaction fails (i.e. a `PDOException` was thrown), the code will be executed again in a new transaction. Therefore the code must not have any side effects besides SQL statements. Also the isolation level should be conserved for the repeated transaction. If the code throws an exception, the transaction is rolled back and not replayed again.

Example:

```
$mutex = new TransactionalMutex($pdo);
$mutex->synchronized(function () use ($pdo, $accountId, $amount) {
    $select = $pdo->prepare("SELECT balance FROM account WHERE id = ? FOR UPDATE");
    $select->execute([$accountId]);
    $balance = $select->fetchColumn();

    $balance -= $amount;
    if ($balance < 0) {
        throw new \DomainException("You have no credit.");

    }
    $pdo->prepare("UPDATE account SET balance = ? WHERE id = ?")
        ->execute([$balance, $accountId]);
});
```

#### MySQLMutex

[](#mysqlmutex)

The **MySQLMutex** uses MySQL's [`GET_LOCK`](https://dev.mysql.com/doc/refman/8.0/en/miscellaneous-functions.html#function_get-lock)function.

It supports time outs. If the connection to the database server is lost or interrupted, the lock is automatically released.

Note that before MySQL 5.7.5 you cannot use nested locks, any new lock will silently release already held locks. You should probably refrain from using this mutex on MySQL versions &lt; 5.7.5.

```
$pdo = new PDO("mysql:host=localhost;dbname=test", "username");

$mutex = new MySQLMutex($pdo, "balance", 15);
$mutex->synchronized(function () use ($bankAccount, $amount) {
    $balance = $bankAccount->getBalance();
    $balance -= $amount;
    if ($balance < 0) {
        throw new \DomainException("You have no credit.");

    }
    $bankAccount->setBalance($balance);
});
```

#### PgAdvisoryLockMutex

[](#pgadvisorylockmutex)

The **PgAdvisoryLockMutex** uses PostgreSQL's [advisory locking](https://www.postgresql.org/docs/9.4/static/functions-admin.html#FUNCTIONS-ADVISORY-LOCKS)functions.

Named locks are offered. PostgreSQL locking functions require integers but the conversion is handled automatically.

No time outs are supported. If the connection to the database server is lost or interrupted, the lock is automatically released.

```
$pdo = new PDO("pgsql:host=localhost;dbname=test;", "username");

$mutex = new PgAdvisoryLockMutex($pdo, "balance");
$mutex->synchronized(function () use ($bankAccount, $amount) {
    $balance = $bankAccount->getBalance();
    $balance -= $amount;
    if ($balance < 0) {
        throw new \DomainException("You have no credit.");

    }
    $bankAccount->setBalance($balance);
});
```

License and authors
-------------------

[](#license-and-authors)

This project is free and under the WTFPL. Responsible for this project is Willem Stuursma-Ruwen .

Donations
---------

[](#donations)

If you like this project and feel generous donate a few Bitcoins here: 1P5FAZ4QhXCuwYPnLZdk3PJsqePbu1UDDA

###  Health Score

28

—

LowBetter than 54% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity2

Limited adoption so far

Community12

Small or concentrated contributor base

Maturity68

Established project with proven stability

 Bus Factor2

2 contributors hold 50%+ of commits

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~73 days

Recently: every ~0 days

Total

21

Last Release

2491d ago

Major Versions

0.4 → 1.0.02016-08-05

v1.4 → v2.02018-11-08

PHP version history (5 changes)0.1PHP &gt;=5.5

1.0.0PHP &gt;=5.6

v2.0PHP &gt;=7.1

v2.6PHP &gt;=7.0

v2.7PHP ~7.0

### Community

Maintainers

![](https://www.gravatar.com/avatar/c6a4e3d3a956bc828f4cdc76cc69932a8a25d2ee187bcd1221cccd42f7094d32?d=identicon)[m-rubin-itmegastar-com](/maintainers/m-rubin-itmegastar-com)

---

Top Contributors

[![willemstuursma](https://avatars.githubusercontent.com/u/701299?v=4)](https://github.com/willemstuursma "willemstuursma (69 commits)")[![malkusch](https://avatars.githubusercontent.com/u/1623984?v=4)](https://github.com/malkusch "malkusch (64 commits)")[![TheLevti](https://avatars.githubusercontent.com/u/7612582?v=4)](https://github.com/TheLevti "TheLevti (45 commits)")[![m-rubin-itmegastar-com](https://avatars.githubusercontent.com/u/43198654?v=4)](https://github.com/m-rubin-itmegastar-com "m-rubin-itmegastar-com (7 commits)")[![Furgas](https://avatars.githubusercontent.com/u/715407?v=4)](https://github.com/Furgas "Furgas (2 commits)")[![glensc](https://avatars.githubusercontent.com/u/199095?v=4)](https://github.com/glensc "glensc (1 commits)")

---

Tags

mysqlpostgresqlredissemaphoremutexlockingcasflockredlockmemcachelockadvisory-locks

###  Code Quality

Code StylePHP\_CodeSniffer

### Embed Badge

![Health badge](/badges/m-rubin-itmegastar-com-lock/health.svg)

```
[![Health](https://phpackages.com/badges/m-rubin-itmegastar-com-lock/health.svg)](https://phpackages.com/packages/m-rubin-itmegastar-com-lock)
```

###  Alternatives

[malkusch/lock

Mutex library for exclusive code execution.

9459.6M27](/packages/malkusch-lock)[arvenil/ninja-mutex

Simple to use mutex implementation that can use flock, memcache, memcached, mysql or redis for locking

1873.7M27](/packages/arvenil-ninja-mutex)[symfony/lock

Creates and manages locks, a mechanism to provide exclusive access to a shared resource

514127.6M459](/packages/symfony-lock)[doctrine/dbal

Powerful PHP database abstraction layer (DBAL) with many features for database schema introspection and management.

9.7k578.4M5.6k](/packages/doctrine-dbal)[matthiasmullie/scrapbook

Scrapbook is a PHP cache library, with adapters for e.g. Memcached, Redis, Couchbase, APCu, SQL and additional capabilities (e.g. transactions, stampede protection) built on top.

3212.5M32](/packages/matthiasmullie-scrapbook)[desarrolla2/cache

Provides an cache interface for several adapters Apc, Apcu, File, Mongo, Memcache, Memcached, Mysql, Mongo, Redis is supported.

1322.5M47](/packages/desarrolla2-cache)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
