1. 程式人生 > 程式設計 >swoole鎖的機制程式碼例項講解

swoole鎖的機制程式碼例項講解

鎖,這個詞我們並不陌生,主要的應用場景會發生在高併發下進行鎖。今天的這篇文章咱們主要來講解一下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、讀寫鎖

int swRWLock_create(swLock *lock, int use_in_process)
{
    int ret;
    bzero(lock, sizeof(swLock));//鎖空間初始化
    lock->type = SW_RWLOCK;//設定鎖的型別為讀寫鎖
    pthread_rwlockattr_init(&lock->object.rwlock.attr);//linux函式,鎖屬性資訊初始化
    if (use_in_process == 1)//標記為在程序中使用,這裡pthread開頭的linux函式預設都是針對執行緒的
    {
        //設定鎖的屬性資訊,標記為在程序中使用
        pthread_rwlockattr_setpshared(&lock->object.rwlock.attr, PTHREAD_PROCESS_SHARED);
    }
 
    if ((ret = pthread_rwlock_init(&lock->object.rwlock._lock, &lock->object.rwlock.attr)) < 0)//linux函式,鎖資訊初始化
    {
        return SW_ERR;
    }
 
    /*
     * 設定鎖的回撥函式
     */
    lock->lock_rd = swRWLock_lock_rd;
    lock->lock = swRWLock_lock_rw;
    lock->unlock = swRWLock_unlock;
    lock->trylock = swRWLock_trylock_rw;
    lock->trylock_rd = swRWLock_trylock_rd;
    lock->free = swRWLock_free;
    return SW_OK;
}
 
 

2、檔案鎖。

int swFileLock_create(swLock *lock, FEGQmint fd)
{
    bzero(lock, sizeof(swLock));//鎖物件資訊初始化
    lock->type = SW_FILELOCK;//設定鎖的型別為檔案鎖
 
    /*
     * 設定鎖的回撥函式
     */
    lock->object.filelock.fd = fd;
    lock->lock_rd = swFileLock_lock_rd;
    lock->lock = swFileLock_lock_rw;
    lock->trylock_rd = swFileLock_trylock_rd;
    lock->trylock = swFileLock_trylock_rw;
    lock->unlock = swFileLock_unlock;
    lock->free = swFileLock_free;
    return 0;
}

3、訊號量鎖

int swSem_create(swLock *lock, key_t key)
{
    int ret;
    lock->type = SW_SEM;//設定鎖型別為訊號量鎖
    if ((ret = semget(key, 1, IPC_CREAT | 0666)) < 0)//建立訊號量,這裡設定的屬性IPC_CREAT,這表示這種訊號量只能用於有親緣關係的程序間
    {
        return SW_ERR;
    }
 
    if (semctl(ret, 0, SETVAL, 1) == -1)//設定訊號量ret的值為1
    {
        swWarn("semctl(SETVAL) failed");
        return SW_ERR;
    }
    lock->object.sem.semid = ret;//設定訊號量ID
 
    /*
     * 設定回撥函式
     */
    lock->lock = swSem_lock;
    lock->unlock = swSem_unlock;
    lock->free = swSem_free;
 
    return SW_OK;
}
 
 

4、樂觀鎖

int swSpinLock_create(swLock *lock, sizeof(swLock));//初始化鎖物件
    lock->type = SW_SPINLOCK;//設定鎖的型別為樂觀鎖
    //執行鎖的初始化操作,這裡指明是在多程序中使用
    if ((ret = pthread_spin_init(&lock->object.spinlock.lock_t, use_in_process)) < 0)
    {
        return -1;
    }
 
    /*
     * 設定回撥函式資訊
   http://www.cppcns.com  */
    lock->lock = swSpinLock_lock;
    lock->unlock = swSpinLock_unlock;
    lock->trylock = swSpinLock_trylock;
    lock->free = swSpinLock_free;
    return 0;
}

5、互斥量鎖

int swMutex_create(swLock *lock, sizeof(swLock));
    lock->type = SW_MUTEX;
    pthread_mutexattr_init(&lock->object.mutex.attr);
    if (use_in_process == 1)
  www.cppcns.com;  {
        pthread_mutexattr_setpshared(&lock->object.mutex.attr, PTHREAD_PROCESS_SHARED);
    }
    if ((ret = pthread_mutex_init(&lock->object.mutex._lock, &lock->object.mutex.attr)) < 0)
    程式設計客棧;{
        return SW_ERR;
    }
    lock->lock = swMutex_lock;
    lock->unlock = swMutex_unlock;
    lock->trylock = swMutex_trylock;
    lock->free = swMutex_free;
    return SW_OK;
}

到此這篇關於swoole鎖的機制程式碼例項講解的文章就介紹到這了,更多相關swoole鎖的機制內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!