swoole鎖的機制代碼實例講解
鎖,這個詞我們并不陌生,主要的應(yīng)用場景會發(fā)生在高并發(fā)下進行鎖。今天的這篇文章咱們主要來講解一下swoole的鎖的機制,swoole_lock是如何實現(xiàn)的。
swoole_lock類支持5種鎖的類型:
- 文件鎖 SWOOLE_FILELOCK
- 讀寫鎖 SWOOLE_RWLOCK
- 信號量 SWOOLE_SEM
- 互斥鎖 SWOOLE_MUTEX
- 自旋鎖 SWOOLE_SPINLOCK
創(chuàng)建這些鎖的過程其實就是調(diào)用構(gòu)造函數(shù)的過程,調(diào)用的形式如下:
swoole_lock->__construct(int $type, [string $lockfile])
$type為鎖的類型
$lockfile,當類型為SWOOLE_FILELOCK時必須傳入,指定文件鎖的路徑
下面我們介紹下這個鎖的實現(xiàn)
static PHP_METHOD(swoole_lock, __construct) { long type = SW_MUTEX; char *filelock; zend_size_t filelock_len = 0; int ret; //解析輸入?yún)?shù),這里輸入?yún)?shù)有2個,其中type表示鎖的類型,另外個參數(shù)是文件鎖時必須傳入(表示文件鎖對應(yīng)的文件路徑),其他鎖時,不需要這個參數(shù) if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ls", &type, &filelock, &filelock_len) == FAILURE) { RETURN_FALSE; } //從內(nèi)存池申請鎖對象空間,這里僅僅是申請鎖空間 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遍歷,創(chuàng)建鎖對象 { #ifdef HAVE_RWLOCK case SW_RWLOCK://如果是讀寫鎖 ret = swRWLock_create(lock, 1);//創(chuàng)建鎖對象,類型為讀寫鎖 break; #endif case SW_FILELOCK://如果是文件鎖 if (filelock_len <= 0)//第二個參數(shù)有效性檢查 { 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) //調(diào)用linux函數(shù)open,打開文件(不存在則創(chuàng)建) { 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);//創(chuàng)建鎖對象,類型為文件鎖 break; case SW_SEM: ret = swSem_create(lock, IPC_PRIVATE);//創(chuàng)建鎖對象,類型為信號量 break; #ifdef HAVE_SPINLOCK case SW_SPINLOCK: ret = swSpinLock_create(lock, 1);//創(chuàng)建鎖對象,類型為樂觀鎖 break; #endif case SW_MUTEX: default: ret = swMutex_create(lock, 1);//創(chuàng)建鎖對象,類型為互斥量 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側(cè)的對象和swoole內(nèi)部對象關(guān)聯(lián) RETURN_TRUE; }
以下分別介紹下各個不同鎖對象的創(chuàng)建過程。
1、讀寫鎖
int swRWLock_create(swLock *lock, int use_in_process) { int ret; bzero(lock, sizeof(swLock));//鎖空間初始化 lock->type = SW_RWLOCK;//設(shè)置鎖的類型為讀寫鎖 pthread_rwlockattr_init(&lock->object.rwlock.attr);//linux函數(shù),鎖屬性信息初始化 if (use_in_process == 1)//標記為在進程中使用,這里pthread開頭的linux函數(shù)默認都是針對線程的 { //設(shè)置鎖的屬性信息,標記為在進程中使用 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函數(shù),鎖信息初始化 { return SW_ERR; } /* * 設(shè)置鎖的回調(diào)函數(shù) */ 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, int fd) { bzero(lock, sizeof(swLock));//鎖對象信息初始化 lock->type = SW_FILELOCK;//設(shè)置鎖的類型為文件鎖 /* * 設(shè)置鎖的回調(diào)函數(shù) */ 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;//設(shè)置鎖類型為信號量鎖 if ((ret = semget(key, 1, IPC_CREAT | 0666)) < 0)//創(chuàng)建信號量,這里設(shè)置的屬性IPC_CREAT,這表示這種信號量只能用于有親緣關(guān)系的進程間 { return SW_ERR; } if (semctl(ret, 0, SETVAL, 1) == -1)//設(shè)置信號量ret的值為1 { swWarn("semctl(SETVAL) failed"); return SW_ERR; } lock->object.sem.semid = ret;//設(shè)置信號量ID /* * 設(shè)置回調(diào)函數(shù) */ lock->lock = swSem_lock; lock->unlock = swSem_unlock; lock->free = swSem_free; return SW_OK; }
4、樂觀鎖
int swSpinLock_create(swLock *lock, int use_in_process) { int ret; bzero(lock, sizeof(swLock));//初始化鎖對象 lock->type = SW_SPINLOCK;//設(shè)置鎖的類型為樂觀鎖 //執(zhí)行鎖的初始化操作,這里指明是在多進程中使用 if ((ret = pthread_spin_init(&lock->object.spinlock.lock_t, use_in_process)) < 0) { return -1; } /* * 設(shè)置回調(diào)函數(shù)信息 */ lock->lock = swSpinLock_lock; lock->unlock = swSpinLock_unlock; lock->trylock = swSpinLock_trylock; lock->free = swSpinLock_free; return 0; }
5、互斥量鎖
int swMutex_create(swLock *lock, int use_in_process) { int ret; bzero(lock, sizeof(swLock)); lock->type = SW_MUTEX; pthread_mutexattr_init(&lock->object.mutex.attr); if (use_in_process == 1) { 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; }
到此這篇關(guān)于swoole鎖的機制代碼實例講解的文章就介紹到這了,更多相關(guān)swoole鎖的機制內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 詳解PHP Swoole與TCP三次握手
- Swoole擴展的6種模式深入詳解
- php中Swoole的熱更新實現(xiàn)代碼實例
- windows系統(tǒng)php環(huán)境安裝swoole具體步驟
- linux系統(tǒng)虛擬主機開啟支持Swoole Loader擴展的方法
- Swoole源碼中如何查詢Websocket的連接問題詳解
- 在Windows系統(tǒng)上安裝Cygwin搭建Swoole測試環(huán)境的圖文教程
- php使用goto實現(xiàn)自動重啟swoole、reactphp、workerman服務(wù)的代碼
- Centos7安裝swoole擴展操作示例
- 詳解Swoole TCP流數(shù)據(jù)邊界問題解決方案
相關(guān)文章
Yii2框架視圖(View)操作及Layout的使用方法分析
這篇文章主要介紹了Yii2框架視圖(View)操作及Layout的使用方法,結(jié)合具體實例形式分析了Yii2框架視圖操作及布局layout相關(guān)操作技巧,需要的朋友可以參考下2019-05-05Thinkphp使用mongodb數(shù)據(jù)庫實現(xiàn)多條件查詢方法
這篇文章主要介紹了Thinkphp使用mongodb數(shù)據(jù)庫實現(xiàn)多條件查詢方法,修改了mongodb驅(qū)動文件來實現(xiàn)復(fù)合查詢、多條件查詢,需要的朋友可以參考下2014-06-06Swoole?webSocket客服IM消息系統(tǒng)方案解析
這篇文章主要為大家介紹了Swoole?webSocket客服IM消息系統(tǒng)方案解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-03-03