# DistributedLock.Postgres
[Download the NuGet package](https://www.nuget.org/packages/DistributedLock.Postgres) [](https://www.nuget.org/packages/DistributedLock.Postgres/)
The DistributedLock.Postgres package offers distributed synchronization primitives based on [PostgreSQL advisory locks](https://www.postgresql.org/docs/9.4/explicit-locking.html#ADVISORY-LOCKS). For example:
```C#
var @lock = new PostgresDistributedLock(new PostgresAdvisoryLockKey("MyLockName", allowHashing: true), connectionString);
await using (await @lock.AcquireAsync())
{
// I have the lock
}
```
## APIs
- The `PostgresDistributedLock` class implements the `IDistributedLock` interface.
- The `PostgresDistributedReaderWriterLock` class implements the `IDistributedReaderWriterLock` interface.
- The `PostgresDistributedSynchronizationProvider` class implements the `IDistributedLockProvider` and `IDistributedReaderWriterLockProvider` interfaces.
## Implementation notes
Under the hood, [Postgres advisory locks can be based on either one 64-bit integer value or a pair of 32-bit integer values](https://www.postgresql.org/docs/12/functions-admin.html#FUNCTIONS-ADVISORY-LOCKS). Because of this, rather than taking in a name the lock constructors take a `PostgresAdvisoryLockKey` object which can be constructed in several ways:
- Passing a single `long` value.
- Passing a pair of `int` values.
- Passing a 16-character hex string (e. g. `"00000003ffffffff"`) which will be parsed as a `long`.
- Passing a pair of comma-separated 8-character hex strings (e. g. `"00000003,ffffffff"`) which will be parsed as a pair of `int`s.
- Passing an ASCII string with 0-9 characters, which will be mapped to a `long` based on a custom scheme.
- Passing an arbitrary string with the `allowHashing` option set to `true` which will be hashed to a `long`. Note that hashing will only be used if other methods of interpreting the string fail.
In addition to specifying the `key`, Postgres-based locks allow you to specify either a `connectionString`, an `IDbConnection`, or a `DbDataSource` as a means of connecting to the database. In most cases, using a `connectionString` is preferred because it allows for the library to efficiently multiplex connections under the hood and, in the case of `IDbConnection`, eliminates the risk that the passed-in `IDbConnection` gets used in a way that disrupts the locking process. **NOTE that since `IDbConnection` objects are not thread-safe, lock objects constructed with them can only be used by one thread at a time.**
## Options
In addition to specifying the `key`, several tuning options are available for `connectionString`-based locks:
- `KeepaliveCadence` allows you to have the implementation periodically issue a cheap query on a connection holding a lock. This helps in configurations which are set up to aggressively kill idle connections. Defaults to OFF (`Timeout.InfiniteTimeSpan`).
- `UseTransaction` scopes the lock to an internally-managed transaction under the hood (otherwise it is connection-scoped). Defaults to FALSE because this mode is not compatible with multiplexing and thus consumes more connections.
- `UseMultiplexing` allows the implementation to re-use connections under the hood to hold multiple locks under certain scenarios, leading to lower resource consumption. This behavior defaults to ON; you should not disable it unless you suspect that it is causing issues for you (please file an issue here if so!).