Skip to content

Commit 2709ee4

Browse files
committed
Add example of a ReadWrite lock
1 parent 67a851b commit 2709ee4

File tree

5 files changed

+169
-2
lines changed

5 files changed

+169
-2
lines changed

cli.php

+119
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
$app = new LockApplication();
1919

2020
$app->addStore('flock', new FlockStore(sys_get_temp_dir()));
21+
$app->addStore('semaphore', new SemaphoreStore());
2122

2223
$app->command('resource:reset [resource]', function ($output, $factory, $input) {
2324
$resourceName = $input->getArgument('resource');
@@ -51,4 +52,122 @@
5152
});
5253

5354

55+
$app->command('barrier', function (OutputInterface $output, Factory $factory) {
56+
$processes = new UnsafeSharedResource('processes');
57+
$barrierFlag = new UnsafeSharedResource('barrier');
58+
59+
$counterLock = $factory->createLock('processes-counter');
60+
$barrierLock = $factory->createLock('processes-barrier');
61+
62+
$heavyWork = function () use ($output) {
63+
$output->writeln("Working");
64+
sleep(rand(1, 5));
65+
};
66+
67+
68+
do {
69+
$processesCount = 0;
70+
$iAmFirstProcess = false;
71+
72+
$counterLock->acquire(true);
73+
try {
74+
$output->writeln("Waiting!!");
75+
$processNumber = $processes->increase();
76+
if ($processNumber == 1) {
77+
$barrierLock->acquire(true);
78+
try {
79+
$barrierFlag->reset();
80+
} finally {
81+
$barrierLock->release();
82+
}
83+
}
84+
} finally {
85+
$counterLock->release();
86+
}
87+
88+
$readBarrierFlag = 0;
89+
do {
90+
$counterLock->acquire(true);
91+
try {
92+
$processesCount = $processes->read();
93+
if ($processesCount == 4) {
94+
$barrierLock->acquire(true);
95+
try {
96+
$output->writeln("----------");
97+
$barrierFlag->increase();
98+
$processes->reset();
99+
} finally {
100+
$barrierLock->release();
101+
}
102+
}
103+
$barrierLock->acquire(true);
104+
try {
105+
$readBarrierFlag = $barrierFlag->read();
106+
} finally {
107+
$barrierLock->release();
108+
}
109+
} finally {
110+
$counterLock->release();
111+
}
112+
} while ($readBarrierFlag === 0);
113+
114+
$heavyWork();
115+
} while (true);
116+
});
117+
118+
$app->command('rw:reader', function (OutputInterface $output, Factory $factory) {
119+
$resource = new UnsafeSharedResource('very-important-thing');
120+
$readersStore = new UnsafeSharedResource('readers');
121+
$readLock = $factory->createLock('reader');
122+
$writeLock = $factory->createLock('writer');
123+
do {
124+
$readLock = $factory->createLock('reader');
125+
$writeLock = $factory->createLock('writer');
126+
127+
// begin read
128+
$readLock->acquire(true);
129+
$readers = $readersStore->increase();
130+
131+
if ($readers == 1) {
132+
$writeLock->acquire(true);
133+
}
134+
$readLock->release();
135+
136+
// read
137+
$value = $resource->read();
138+
$output->writeln(">> Read $value");
139+
140+
// end read
141+
$readLock->acquire(true);
142+
$readers = $readersStore->decrease();
143+
//$output->writeln(">>>> readers (end): $readers");
144+
if ($readers == 0) {
145+
$writeLock->release();
146+
}
147+
$readLock->release();
148+
sleep(rand(1, 5));
149+
} while (true);
150+
});
151+
152+
153+
$app->command('rw:writer', function (OutputInterface $output, Factory $factory) {
154+
$resource = new UnsafeSharedResource('very-important-thing');
155+
$readLock = $factory->createLock('reader');
156+
$writeLock = $factory->createLock('writer');
157+
do {
158+
//begin write
159+
$writeLock->acquire(true);
160+
$output->writeln('Start to write...');
161+
162+
//write
163+
$resource->increase();
164+
sleep(5);
165+
166+
//end write
167+
$output->writeln('Write finishes!');
168+
$writeLock->release();
169+
} while (true);
170+
});
171+
172+
54173
$app->run();

composer.json

+14-2
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,25 @@
1313
],
1414
"run:simple-nolock": [
1515
"docker-compose exec -T app pm2 delete all || true",
16-
"docker-compose exec -T app php run /app/cli.php resource:reset very-important-thing",
16+
"docker-compose exec -T app php /app/cli.php resource:reset very-important-thing",
1717
"docker-compose exec -T app pm2 start /app/pm2/simple-nolock.yml"
1818
],
1919
"run:simple-lock": [
2020
"docker-compose exec -T app pm2 delete all || true",
21-
"docker-compose exec -T app php run /app/cli.php resource:reset very-important-thing",
21+
"docker-compose exec -T app php /app/cli.php resource:reset very-important-thing",
2222
"docker-compose exec -T app pm2 start /app/pm2/simple-lock.yml"
23+
],
24+
"run:barrier": [
25+
"docker-compose exec -T app pm2 delete all || true",
26+
"docker-compose exec -T app php /app/cli.php resource:reset barrier",
27+
"docker-compose exec -T app php /app/cli.php resource:reset processes",
28+
"docker-compose exec -T app pm2 start /app/pm2/barrier.yml"
29+
],
30+
"run:rw": [
31+
"docker-compose exec -T app pm2 delete all || true",
32+
"docker-compose exec -T app php /app/cli.php resource:reset very-important-thing",
33+
"docker-compose exec -T app php /app/cli.php resource:reset readers",
34+
"docker-compose exec -T app pm2 start /app/pm2/read-write.yml"
2335
]
2436
}
2537
}

pm2/barrier.yml

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
apps:
2+
- name : barrier
3+
script : cli.php
4+
args :
5+
- barrier
6+
- flock
7+
instances : 4
8+
exec_mode : fork
9+
cwd : /app
10+
interpreter : /usr/bin/php

pm2/read-write.yml

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
apps:
2+
- name : rw:reader
3+
script : cli.php
4+
args :
5+
- rw:reader
6+
- semaphore
7+
instances : 10
8+
exec_mode : fork
9+
cwd : /app
10+
interpreter : /usr/bin/php
11+
- name : rw:writer
12+
script : cli.php
13+
args :
14+
- rw:writer
15+
- semaphore
16+
instances : 1
17+
exec_mode : fork
18+
cwd : /app
19+
interpreter : /usr/bin/php

src/LockExamples/Resource/UnsafeSharedResource.php

+7
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,13 @@ public function increase()
2828
return $value;
2929
}
3030

31+
public function decrease()
32+
{
33+
$value = $this->read();
34+
$this->write(--$value);
35+
return $value;
36+
}
37+
3138
public function reset()
3239
{
3340
$this->write(0);

0 commit comments

Comments
 (0)