If you need non-blocking semaphores, here is an example how you may implement it. Use a shared memory variable to mark whether or not a lock exists and then use a semaphore around operations against that variable. I'll call my shared variable as 'token'.
<?php
echo '<pre>';
$resourceSemaphore = sem_get(7);
$tokenSemaphore = sem_get(8);
$tokenValue = shm_attach(9, 100);
function myEcho($v) {
echo microtime() . ' ' . $v . "\n";
}
function try_lock() {
global $resourceSemaphore, $tokenSemaphore, $tokenValue;
myEcho('begin try_lock()');
myEcho('acquire token semaphore');
sem_acquire($tokenSemaphore);
myEcho(' token semaphore acquired');
$tmp = shm_get_var($tokenValue, 6);
myEcho(' token value: ' . var_export($tmp, true));
$exit = $tmp;
if (!$exit) {
$tmp = shm_put_var($tokenValue, 6, true);
$tmp = shm_get_var($tokenValue, 6);
myEcho(' token new value: ' . var_export($tmp, true));
}
myEcho('release token semaphore');
sem_release($tokenSemaphore);
if ($exit) return false;
myEcho('acquire resource semaphore');
sem_acquire($resourceSemaphore);
myEcho(' resource semaphore acquired');
return true;
}
function release() {
global $resourceSemaphore, $tokenSemaphore, $tokenValue;
myEcho('release resource semaphore');
sem_release($resourceSemaphore);
myEcho('acquire token semaphore');
sem_acquire($tokenSemaphore);
myEcho(' token semaphore acquired');
$tmp = shm_get_var($tokenValue, 6);
myEcho(' token value: ' . var_export($tmp, true));
$tmp = shm_put_var($tokenValue, 6, false);
$tmp = shm_get_var($tokenValue, 6);
myEcho(' token new value: ' . var_export($tmp, true));
myEcho('release token semaphore');
sem_release($tokenSemaphore);
}
for ($triesLeft = 5; $triesLeft > 0 && !try_lock(); $triesLeft--) {
myEcho('failed to acquire resource');
myEcho('wait for 1 sec');
sleep(1);
myEcho('try again');
}
myEcho(' access the resource for 4 sec');
sleep(4);
release();
myEcho('the end');
?>
When I execute this script in two parallel instances, I get the following output:
-------(first instance)----------------------------------------
... 482 begin try_lock()
... 482 acquire token semaphore
... 482 token semaphore acquired
... 482 token value: false
... 482 token new value: true
... 482 release token semaphore
... 482 acquire resource semaphore
... 482 resource semaphore acquired
... 482 access the resource for 4 sec
... 486 release resource semaphore
... 486 acquire token semaphore
... 486 token semaphore acquired
... 486 token value: true
... 486 token new value: false
... 486 release token semaphore
... 486 the end
-------(second instance)----------------------------------------
... 485 begin try_lock()
... 485 acquire token semaphore
... 485 token semaphore acquired
... 485 token value: true
... 485 release token semaphore
... 485 failed to acquire resource
... 485 wait for 1 sec
...
... 486 wait for 1 sec
... 487 try again
... 487 begin try_lock()
... 487 acquire token semaphore
... 487 token semaphore acquired
... 487 token value: false
... 487 token new value: true
... 487 release token semaphore
... 487 acquire resource semaphore
... 487 resource semaphore acquired
... 487 access the resource for 4 sec
... 491 release resource semaphore
... 491 acquire token semaphore
... 491 token semaphore acquired
... 491 token value: true
... 491 token new value: false
... 491 release token semaphore
... 491 the end