首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在php中获得锁的最好方法

在php中获得锁的最好方法
EN

Stack Overflow用户
提问于 2008-11-28 13:50:34
回答 9查看 41.4K关注 0票数 18

我正在尝试更新APC中的一个变量,将有许多进程尝试这样做。

APC不提供锁定功能,所以我正在考虑使用其他机制...到目前为止,我找到的是mysql的GET_LOCK()和php的flock()。还有什么值得考虑的吗?

更新:我找到了sem_acquire,但它似乎是一个阻塞锁。

EN

回答 9

Stack Overflow用户

发布于 2010-10-13 18:37:51

/*
CLASS ExclusiveLock
Description
==================================================================
This is a pseudo implementation of mutex since php does not have
any thread synchronization objects
This class uses flock() as a base to provide locking functionality.
Lock will be released in following cases
1 - user calls unlock
2 - when this lock object gets deleted
3 - when request or script ends
==================================================================
Usage:

//get the lock
$lock = new ExclusiveLock( "mylock" );

//lock
if( $lock->lock( ) == FALSE )
    error("Locking failed");
//--
//Do your work here
//--

//unlock
$lock->unlock();
===================================================================
*/
class ExclusiveLock
{
    protected $key   = null;  //user given value
    protected $file  = null;  //resource to lock
    protected $own   = FALSE; //have we locked resource

    function __construct( $key ) 
    {
        $this->key = $key;
        //create a new resource or get exisitng with same key
        $this->file = fopen("$key.lockfile", 'w+');
    }


    function __destruct() 
    {
        if( $this->own == TRUE )
            $this->unlock( );
    }


    function lock( ) 
    {
        if( !flock($this->file, LOCK_EX | LOCK_NB)) 
        { //failed
            $key = $this->key;
            error_log("ExclusiveLock::acquire_lock FAILED to acquire lock [$key]");
            return FALSE;
        }
        ftruncate($this->file, 0); // truncate file
        //write something to just help debugging
        fwrite( $this->file, "Locked\n");
        fflush( $this->file );

        $this->own = TRUE;
        return TRUE; // success
    }


    function unlock( ) 
    {
        $key = $this->key;
        if( $this->own == TRUE ) 
        {
            if( !flock($this->file, LOCK_UN) )
            { //failed
                error_log("ExclusiveLock::lock FAILED to release lock [$key]");
                return FALSE;
            }
            ftruncate($this->file, 0); // truncate file
            //write something to just help debugging
            fwrite( $this->file, "Unlocked\n");
            fflush( $this->file );
            $this->own = FALSE;
        }
        else
        {
            error_log("ExclusiveLock::unlock called on [$key] but its not acquired by caller");
        }
        return TRUE; // success
    }
};
票数 17
EN

Stack Overflow用户

发布于 2008-12-02 19:53:50

如果锁的目的是防止多个进程试图填充一个空的缓存键,那么为什么不想要一个阻塞锁呢?

  $value = apc_fetch($KEY);

  if ($value === FALSE) {
      shm_acquire($SEMAPHORE);

      $recheck_value = apc_fetch($KEY);
      if ($recheck_value !== FALSE) {
        $new_value = expensive_operation();
        apc_store($KEY, $new_value);
        $value = $new_value;
      } else {
        $value = $recheck_value;
      }

      shm_release($SEMAPHORE);
   }

如果缓存很好,你可以直接使用它。如果缓存中什么都没有,你就会得到一个锁。一旦获得了锁,就需要仔细检查缓存,以确保在等待获取锁的过程中,缓存没有被重新填充。如果缓存被重新填充,则使用该值并释放锁,否则,执行计算,填充缓存,然后释放锁。

票数 5
EN

Stack Overflow用户

发布于 2008-11-30 23:22:57

如果你不介意将锁建立在文件系统上,那么你可以使用fopen()和模式'x‘。下面是一个示例:

$f = fopen("lockFile.txt", 'x');
if($f) {
    $me = getmypid();
    $now = date('Y-m-d H:i:s');
    fwrite($f, "Locked by $me at $now\n");
    fclose($f);
    doStuffInLock();
    unlink("lockFile.txt"); // unlock        
}
else {
    echo "File is locked: " . file_get_contents("lockFile.txt");
    exit;
}

参见www.php.net/fopen

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/325806

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档