在Python 3中,我想获取一个锁,然后知道它是否被阻塞。问题在于,如果threading.Lock.acquire
被True
调用,则总是返回blocking=True
,因此无法得知调用该函数时该锁是否已经被锁定。以下面的代码为例:
import threading
foo = None
lock = threading.Lock()
def bar():
global foo
# Only compute foo in one thread at a time.
if not lock.acquire(blocking=False):
# The race condition exists here.
# Another thread is already computing foo.
# This instance does not need to recompute foo.
# Wait for that instance to finish.
with lock:
# Just return the value that the other instance computed.
return foo
# No other instance of this function is computing foo.
with lock:
# Compute foo.
foo = [something]
return foo
这里的问题是,lock
可以再次获得,其中上面代码中的注释指出存在竞争条件。
如果这是因为第三个线程在该函数中的同一点先继续并获得了锁,则这是不希望的,因为它会引入一些延迟。 return foo
确实没有理由需要受到保护;两个线程应该能够同时执行此操作。
但是,如果获取是由于另一个线程重新计算foo
导致的,那么这是不希望的,因为一旦释放锁,foo
就会发生变化。该函数应返回在调用时正在计算的foo
的值。如果foo
发生变化,那么它将无法再返回该值。
理想情况下,我们将拥有一个acquire
函数,该函数可以阻止并仍然返回是否阻止。这样,我们可以放心地断言该函数总是返回调用该函数时正在计算的foo
的值,并且只有在尚未foo
进行计算的情况下,该函数才会继续执行,计算它,并返回新值。可以用Python完成吗?
答案 0 :(得分:2)
我知道这个问题很老了,但由于我在寻找其他问题时偶然发现了它并且没有答案,我想我会做任何找到它的服务并回答它的人。
您首先检查锁是否可用,从而导致了竞争条件。您应该尝试在不检查的情况下获取锁,如下所示:
public $const = [
"aws_endpoint" => "https://ip:port",
"aws_key" => "login",
"aws_secret" => "***********",
"aws_bucket" => "testbucket",
];
$s3 = Aws\S3\S3Client::factory([
'version' => 'latest',
'region' => 'eu-north-1',
'endpoint' => $this->const["aws_endpoint"],
'credentials' => [
'key' => $this->const["aws_key"],
'secret' => $this->const["aws_secret"],
],
]);
return $s3->putObject([
'Bucket' => $this->const["aws_bucket"],
'Key' => $objectKey,
'SourceFile' => $pathToFile,
'ContentLength' => filesize($pathToFile),
'ContentSHA256' => hash_file("sha256", $pathToFile),
]);