В главных ответах на этой странице используются слишком простые примеры, такие как объект с одним свойством (например, {name: value}). Я думаю, что простой, но реальный пример жизни может помочь кому-то.
Итак, это JSON, возвращенный API-интерфейсом Google Translate:
{
"data":
{
"translations":
[
{
"translatedText": "Arbeit"
}
]
}
}
Я хочу получить значение атрибута «translText», например. «Arbeit» с использованием Google Gson.
Два возможных подхода:
String json = callToTranslateApi("work", "de");
JsonObject jsonObject = new JsonParser().parse(json).getAsJsonObject();
return jsonObject.get("data").getAsJsonObject()
.get("translations").getAsJsonArray()
.get(0).getAsJsonObject()
.get("translatedText").getAsString();
class ApiResponse {
Data data;
class Data {
Translation[] translations;
class Translation {
String translatedText;
}
}
}
... Gson g = new Gson();
String json =callToTranslateApi("work", "de");
ApiResponse response = g.fromJson(json, ApiResponse.class);
return response.data.translations[0].translatedText;
Это связано с тем, что flock()
может потерпеть неудачу не только потому, что замок уже получен где-то в другом месте. В таком случае он не блокирует ожидание блокировки, но сразу же возвращает false. Другими словами, с помощью LOCK_NB
, если flock возвращает false и willblock = 1, значит, он попытался получить блокировку, но он уже получен где-то в другом месте. Но если flock с LOCK_NB
возвращает false и beblock = 0, то это означает, что что-то действительно плохое происходит, и стая даже не рассматривала возможность ожидания блокировки, поскольку это было совершенно невозможно.
Проверьте этот код ( здесь также gist ):
<?php
// Let's create /tmp/ninja-lock1.txt ...
$fp0 = fopen('/tmp/ninja-lock1.txt', 'c');
// ... and close it imiedietly
fclose($fp0);
// File handler $fp0 was closed so flock()
// is unable to use it to gain lock.
// It will fail with wouldblock set to 0
// as it doesn't make sense to wait on unusable file handle.
//
// BTW flock() throws in such case warning "x is not a valid stream resource".
// Just for the purpose of clear output from this example
// I've suppressed it with @ - don't use @ in production
$flockResult = @flock($fp0, LOCK_EX | LOCK_NB, $wouldblock);
printf("flock=%b; wouldblock=%d (Acquire lock: %s)\n", $flockResult, $wouldblock, "failure, broken file handle");
// Two handlers for /tmp/ninja-lock2.txt
// to show flock() blocking result.
$fp1 = fopen('/tmp/ninja-lock2.txt', 'c');
$fp2 = fopen('/tmp/ninja-lock2.txt', 'c');
// Nobody is locking on /tmp/ninja-lock2.txt,
// so it will acquire lock and wouldblock will be 0
$flockResult = flock($fp1, LOCK_EX | LOCK_NB, $wouldblock);
printf("flock=%b; wouldblock=%d (Acquire lock: %s)\n", $flockResult, $wouldblock, "success");
// File is locked on $fp1 handle so flock won't acquire lock
// and wouldblock will be 1
$flockResult = flock($fp2, LOCK_EX | LOCK_NB, $wouldblock);
printf("flock=%b; wouldblock=%d (Acquire lock: %s)\n", $flockResult, $wouldblock, "failure, already acquired somewhere else");
// Result:
// $ php flock.php
// flock=0; wouldblock=0 (Acquire lock: failure, broken file handle)
// flock=1; wouldblock=0 (Acquire lock: success)
// flock=0; wouldblock=1 (Acquire lock: failure, already acquired somewhere else)
?>
Также, чтобы устранить любую путаницу будущих читателей, стоит отметить, что проверка EWOULDBLOCK
имеет смысл только для flock () с флагом LOCK_NB
, так как в режиме блокировки это либо успех, либо блок или сбой, и никакой блок.
Вы можете подтвердить это, посмотрев на php исходный код для flock :
PHPAPI int php_flock(int fd, int operation)
#if HAVE_STRUCT_FLOCK /* {{{ */
{
struct flock flck;
int ret;
flck.l_start = flck.l_len = 0;
flck.l_whence = SEEK_SET;
if (operation & LOCK_SH)
flck.l_type = F_RDLCK;
else if (operation & LOCK_EX)
flck.l_type = F_WRLCK;
else if (operation & LOCK_UN)
flck.l_type = F_UNLCK;
else {
errno = EINVAL;
return -1;
}
ret = fcntl(fd, operation & LOCK_NB ? F_SETLK : F_SETLKW, &flck);
if (operation & LOCK_NB && ret == -1 &&
(errno == EACCES || errno == EAGAIN))
errno = EWOULDBLOCK;
if (ret != -1) ret = 0;
return ret;
}
EWOULDBLOCK
установлен только в том случае, если operation & LOCK_NB && ret == -1 &&
(errno == EACCES || errno == EAGAIN)
.
Если вас больше интересует реализация, вы также можете прочитать man fcntl , в основном части о F_SETLK
и F_SETLKW
:
F_SETLK
Получить блокировку (когда l_type - F_RDLCK или F_WRLCK) или освободить блокировку (когда l_type - F_UNLCK) в байтах, заданных полями l_whence, l_start и l_len блокировки. Если конфликтующая блокировка удерживается другим процессом, этот вызов возвращает -1 и устанавливает errno в EACCES или EAGAIN.
F_SETLKW
Что касается F_SETLK, но если конфликтующая блокировка сохраняется файл, затем дождитесь, когда этот замок будет выпущен. Если сигнал улавливается во время ожидания, то вызов прерывается и (после возврата обработчика сигнала) возвращается немедленно (с возвращаемым значением -1 и errno, установленным в EINTR).
blockquote>