锁,这个词我们并不陌生,主要的应用场景会发生在高并发下进行锁。今天的这篇文章咱们主要来讲解一下swoole的锁的机制,swoole_lock是如何实现的。
swoole_lock类支持5种锁的类型:
文件锁 SWOOLE_FILELOCK
读写锁 SWOOLE_RWLOCK
信号量 SWOOLE_SEM
互斥锁 SWOOLE_MUTEX
自旋锁 SWOOLE_SPINLOCK
创建这些锁的过程其实就是调用构造函数的过程,调用的形式如下:
swoole_lock->__construct(int $type, [string $lockfile])
$type为锁的类型
$lockfile,当类型为SWOOLE_FILELOCK时必须传入,指定文件锁的路径
下面我们介绍下这个锁的实现
static PHP_METHOD(swoole_lock, __construct) { long type = SW_MUTEX; char *filelock; zend_size_t filelock_len = 0; int ret; //解析输入参数,这里输入参数有2个,其中type表示锁的类型,另外个参数是文件锁时必须传入(表示文件锁对应的文件路径),其他锁时,不需要这个参数 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ls", &type, &filelock, &filelock_len) == FAILURE) { RETURN_FALSE; } //从内存池申请锁对象空间,这里仅仅是申请锁空间 swLock *lock = SwooleG.memory_pool->alloc(SwooleG.memory_pool, sizeof(swLock)); if (lock == NULL)//申请空间失败 { zend_throw_exception(swoole_exception_class_entry_ptr, "global memory allocation failure.", SW_ERROR_MALLOC_FAIL TSRMLS_CC); RETURN_FALSE; } switch(type)//按type遍历,创建锁对象 { #ifdef HAVE_RWLOCK case SW_RWLOCK://如果是读写锁 ret = swRWLock_create(lock, 1);//创建锁对象,类型为读写锁 break; #endif case SW_FILELOCK://如果是文件锁 if (filelock_len <= 0)//第二个参数有效性检查 { zend_throw_exception(swoole_exception_class_entry_ptr, "filelock requires file name of the lock.", SW_ERROR_INVALID_PARAMS TSRMLS_CC); RETURN_FALSE; } int fd; if ((fd = open(filelock, O_RDWR | O_CREAT, 0666)) < 0) //调用linux函数open,打开文件(不存在则创建) { zend_throw_exception_ex(swoole_exception_class_entry_ptr, errno TSRMLS_CC, "open file[%s] failed. Error: %s [%d]", filelock, strerror(errno), errno); RETURN_FALSE; } ret = swFileLock_create(lock, fd);//创建锁对象,类型为文件锁 break; case SW_SEM: ret = swSem_create(lock, IPC_PRIVATE);//创建锁对象,类型为信号量 break; #ifdef HAVE_SPINLOCK case SW_SPINLOCK: ret = swSpinLock_create(lock, 1);//创建锁对象,类型为乐观锁 break; #endif case SW_MUTEX: default: ret = swMutex_create(lock, 1);//创建锁对象,类型为互斥量 break; } if (ret < 0) { zend_throw_exception(swoole_exception_class_entry_ptr, "failed to create lock.", errno TSRMLS_CC); RETURN_FALSE; } swoole_set_object(getThis(), lock);//PHP侧的对象和swoole内部对象关联 RETURN_TRUE; }
以下分别介绍下各个不同锁对象的创建过程。
1、读写锁