3
3
single: Components; Lock
4
4
5
5
The Lock Component
6
- ====================
6
+ ==================
7
7
8
8
The Lock Component provides a mechanism to guarantee an exclusive access
9
9
into a critical section. The component ships with ready to use stores for
@@ -26,31 +26,29 @@ Usage
26
26
-----
27
27
28
28
In order to centralize state of locks, you first need to create a ``Store ``.
29
- Then, you can ask to this store to create a Lock for your ``resource ``.
29
+ Then, you can use the :class: `Symfony\\ Component\\ Lock\\ Factory ` to create a
30
+ Lock for your ``resource ``.
30
31
31
32
The :method: `Symfony\\ Component\\ Lock\\ LockInterface::acquire ` method tries to
32
- acquire the lock. If the lock can not be acquired, the method throws a
33
- :class: `Symfony\\ Component\\ Lock\\ Exception\\ LockConflictedException `. You can
34
- safely call the ``acquire() `` method several times, even if you already acquired
35
- it.
33
+ acquire the lock. If the lock can not be acquired, the method returns ``false ``.
34
+ You can safely call the ``acquire() `` method several times, even if you already
35
+ acquired it.
36
36
37
37
.. code-block :: php
38
38
39
+ use Symfony\Component\Lock\Factory;
39
40
use Symfony\Component\Lock\Store\SemaphoreStore;
40
- use Symfony\Component\Lock\Exception\LockConflictedException;
41
41
42
42
$store = new SemaphoreStore();
43
- $lock = $store->createLock('invoice-pdf-generation');
43
+ $factory = new Factory($store);
44
+ $lock = $factory->createLock('invoice-pdf-generation');
44
45
45
- try {
46
- $lock->acquire();
46
+ if ($lock->acquire()) {
47
47
// the resource "invoice-pdf-generation" is locked.
48
48
49
49
// You can compute and generate invoice safely here.
50
50
51
51
$lock->release();
52
- } catch (LockConflictedException $e) {
53
- // the resource "invoice-pdf-generation" is already locked by another process
54
52
}
55
53
56
54
The first argument of ``createLock `` is a string representation of the
@@ -62,9 +60,9 @@ The first argument of ``createLock`` is a string representation of the
62
60
distinguishes locks instances, even when they are created from the same
63
61
``resource ``.
64
62
If you want to share a lock in several services. You have to share the
65
- instance of Lock returned by the ``Store ::createLock `` method.
63
+ instance of Lock returned by the ``Factory ::createLock `` method.
66
64
67
- Blocking locks
65
+ Blocking Locks
68
66
--------------
69
67
70
68
You can pass an optional blocking argument as the first argument to the
@@ -77,70 +75,76 @@ you can decorate it with the ``RetryTillSaveStore``.
77
75
78
76
.. code-block :: php
79
77
78
+ use Symfony\Component\Lock\Factory;
80
79
use Symfony\Component\Lock\Store\RedisStore;
81
80
use Symfony\Component\Lock\Store\RetryTillSaveStore;
82
81
83
82
$store = new RedisStore(new \Predis\Client('tcp://localhost:6379'));
84
83
$store = new RetryTillSaveStore($store);
85
84
86
- $lock = $store->createLock('notification-flush');
85
+ $factory = new Factory($store);
86
+
87
+ $lock = $factory->createLock('notification-flush');
87
88
88
89
$lock->acquire(true);
89
90
90
- Expirable Locks
91
- ---------------
91
+ Expiring Locks
92
+ --------------
92
93
93
- Working with a remote ``Store `` is hard. There is now way for the remote
94
- ``Store `` to know if the locker process is till alive.
94
+ Working with a remote ``Store `` is hard. There is no way for the remote
95
+ ``Store `` to know if the locker process is still alive.
95
96
Due to bugs, fatal errors or segmentation fault, we can't guarantee that the
96
97
``release() `` method will be called, which would cause a ``resource `` to be locked
97
98
infinitely.
98
99
99
- To fill this gap, the remote ``Stores `` provide an expirable mechanism: The lock
100
- is acquired for a defined amount of time (named TTL for Time To Live).
101
- When the timeout occurred , the lock is automatically released even if the locker
100
+ To fill this gap, the remote ``Store `` provide an expiration mechanism: The
101
+ lock is acquired for a defined amount of time (named TTL for Time To Live).
102
+ When the timeout occurs , the lock is automatically released even if the locker
102
103
don't call the ``release() `` method.
103
104
104
- That's why, when you create a lock on an expirable ``Store ``. You have to choose
105
- carefully the correct TTL. When too low, you take the risk to "lose " the lock
105
+ That's why, when you create a lock on an expiring ``Store ``, you have to choose
106
+ carefully the correct TTL. When too low, you take the risk to "loose " the lock
106
107
(and someone else acquire it) whereas you don't finish your task.
107
108
When too high and the process crash before you call the ``release() `` method,
108
109
the ``resource `` will stay lock till the timeout.
109
110
110
-
111
111
.. code-block :: php
112
112
113
+ use Symfony\Component\Lock\Factory;
113
114
use Symfony\Component\Lock\Store\RedisStore;
114
115
115
116
$store = new RedisStore(new \Predis\Client('tcp://localhost:6379'));
116
117
117
- $lock = $store->createLock('charts-generation', 30);
118
+ $factory = new Factory($store);
119
+ $lock = $factory->createLock('charts-generation', 30);
118
120
119
121
$lock->acquire();
120
122
try {
121
123
// perfom a job during less than 30 seconds
122
124
} finally {
123
- $lock->release()
125
+ $lock->release();
124
126
}
125
127
126
128
.. tip ::
127
129
128
130
To avoid letting the Lock in a locking state, try to always release an
129
- expirable lock by wrapping the job in a try/catch block for instance.
131
+ expiring lock by wrapping the job in a try/catch block for instance.
130
132
131
133
When you have to work on a really long task, you should not set the TTL to
132
- overlap the duration of this task. Instead, the Lock Component expose a
134
+ overlap the duration of this task. Instead, the Lock Component exposes a
133
135
:method: `Symfony\\ Component\\ Lock\\ LockInterface::refresh ` method in order to
134
136
put off the TTL of the Lock. Thereby you can choose a small initial TTL, and
135
- regularly refresh the lock
137
+ regularly refresh the lock.
136
138
137
139
.. code-block :: php
138
140
141
+ use Symfony\Component\Lock\Factory;
139
142
use Symfony\Component\Lock\Store\RedisStore;
140
143
141
144
$store = new RedisStore(new \Predis\Client('tcp://localhost:6379'));
142
145
143
- $lock = $store->createLock('charts-generation', 30);
146
+ $factory = new Factory($store);
147
+ $lock = $factory->createLock('charts-generation', 30);
144
148
145
149
$lock->acquire();
146
150
try {
@@ -151,7 +155,7 @@ regularly refresh the lock
151
155
// resource is locked for 30 more seconds.
152
156
}
153
157
} finally {
154
- $lock->release()
158
+ $lock->release();
155
159
}
156
160
157
161
Available Stores
@@ -162,31 +166,31 @@ This component provides several adapters ready to use in your applications.
162
166
163
167
Here is a small summary of available ``Stores `` and their capabilities.
164
168
165
- +----------------------------------------------+--------+----------+----------- +
166
- | Store | Scope | Blocking | Expirable |
167
- +==============================================+========+==========+=========== +
168
- | :ref: `FlockStore <lock-store-flock >` | local | yes | no |
169
- +----------------------------------------------+--------+----------+----------- +
170
- | :ref: `MemcachedStore <lock-store-memcached >` | remote | no | yes |
171
- +----------------------------------------------+--------+----------+----------- +
172
- | :ref: `RedisStore <lock-store-redis >` | remote | no | yes |
173
- +----------------------------------------------+--------+----------+----------- +
174
- | :ref: `SemaphoreStore <lock-store-semaphore >` | local | yes | no |
175
- +----------------------------------------------+--------+----------+----------- +
169
+ +----------------------------------------------+--------+----------+----------+
170
+ | Store | Scope | Blocking | Expiring |
171
+ +==============================================+========+==========+==========+
172
+ | :ref: `FlockStore <lock-store-flock >` | local | yes | no |
173
+ +----------------------------------------------+--------+----------+----------+
174
+ | :ref: `MemcachedStore <lock-store-memcached >` | remote | no | yes |
175
+ +----------------------------------------------+--------+----------+----------+
176
+ | :ref: `RedisStore <lock-store-redis >` | remote | no | yes |
177
+ +----------------------------------------------+--------+----------+----------+
178
+ | :ref: `SemaphoreStore <lock-store-semaphore >` | local | yes | no |
179
+ +----------------------------------------------+--------+----------+----------+
176
180
177
181
.. tip ::
178
182
179
183
Calling the :method: `Symfony\\ Component\\ Lock\\ LockInterface::refresh `
180
- method on a Lock created from a non expirable ``Store `` like
184
+ method on a Lock created from a non expiring ``Store `` like
181
185
:ref: `FlockStore <lock-store-flock >` will do nothing.
182
186
183
187
.. _lock-store-flock :
184
188
185
189
FlockStore
186
190
~~~~~~~~~~
187
191
188
- The FlockStore use the fileSystem on the local computer to lock and store the
189
- ``resource ``. It does not supports expiration, but the lock is automatically
192
+ The FlockStore uses the fileSystem on the local computer to lock and store the
193
+ ``resource ``. It does not support expiration, but the lock is automatically
190
194
released when the PHP process is terminated.
191
195
192
196
.. code-block :: php
@@ -200,7 +204,7 @@ file will be created.
200
204
201
205
.. caution ::
202
206
203
- Beware, some filesystem (like some version of NFS) does not support locking.
207
+ Beware, some filesystems (like some version of NFS) do not support locking.
204
208
We suggest to use local file, or to use a Store dedicated to remote usage
205
209
like Redis or Memcached.
206
210
@@ -212,18 +216,18 @@ MemcachedStore
212
216
~~~~~~~~~~~~~~
213
217
214
218
The MemcachedStore stores state of ``resource `` in a Memcached server. This
215
- ``Store `` does not support blocking, and expect a TLL to avoid infinity locks.
219
+ ``Store `` does not support blocking, and expects a TLL to avoid infinity locks.
216
220
217
221
.. note ::
218
222
219
- Memcached does not supports TTL lower than 1 seconds .
223
+ Memcached does not support TTL lower than 1 second .
220
224
221
225
It requires to have installed Memcached and have created a connection that
222
- implements the ``\Memcached `` classes::
226
+ implements the ``\Memcached `` class.
223
227
224
228
.. code-block :: php
225
229
226
- use Symfony\Component\Lock\Store\RedisStore ;
230
+ use Symfony\Component\Lock\Store\MemcachedStore ;
227
231
228
232
$memcached = new \Memcached();
229
233
$memcached->addServer('localhost', 11211);
@@ -241,7 +245,7 @@ locks.
241
245
242
246
It requires to have installed Redis and have created a connection that
243
247
implements the ``\Redis ``, ``\RedisArray ``, ``\RedisCluster `` or ``\Predis ``
244
- classes::
248
+ classes
245
249
246
250
.. code-block :: php
247
251
@@ -257,13 +261,13 @@ classes::
257
261
SemaphoreStore
258
262
~~~~~~~~~~~~~~
259
263
260
- The SemaphoreStore uses the PHP semaphore function to lock a ``resources ``.
264
+ The SemaphoreStore uses the PHP semaphore functions to lock a ``resources ``.
261
265
262
266
.. code-block :: php
263
267
264
268
use Symfony\Component\Lock\Store\SemaphoreStore;
265
269
266
- $store = new SemaphoreStore($redis );
270
+ $store = new SemaphoreStore();
267
271
268
272
.. _lock-store-combined :
269
273
0 commit comments