文章目錄
- 線程的信号量
-
- 初始化信号量:sem_init
- 減少信号量:sem_wait
- 增加信号量:sem_post
- 删除信号量:sem_destroy
- 代碼示例
- 線程的互斥量
-
- 初始化互斥量:pthread_mutex_init
- 鎖住互斥量:pthread_mutex_lock
- 解鎖互斥量:pthread_mutex_unlock
- 銷毀互斥量:pthread_mutex_destroy
- 代碼示例
線程的信号量
原理簡介:
線程的信号量和程序的類似,維護一個sem_t類型(本質是一個int類型的)的信号量,不同線程通過判斷信号量的值,來決定是否進行繼續運作,進而控制線程運作的先後順序。比如信号量初始化成0,線程1調用sem_wait阻塞住,等待線程2調用sem_post将限号量增加之後,線程1被喚醒,進而實作線程1、2執行的順序。
使用流程:
- sem_init初始化信号量
- sem_post增加信号量
- sem_wait判斷并減少信号量
初始化信号量:sem_init
sem_init用于初始化信号量的初始值和作用範圍。
#include <semaphore.h>
int sem_init(sem_t *sem, int pshared, unsigned int value);
Link with -pthread;
sem: 需要被初始化的信号量對象;
value: 初始值;
pshared: 1)0,表示信号量線程共享,多線程可以共同操作該信号量,要求sem變量的作用域能被多個線程通路到;2)非0,表示信号量程序共享,多程序可以共同操作該信号量,如果是父子程序,要求sem變量的作用域能被多個程序通路到,若父子程序,則可以直接通路,若沒有關系的程序,那麼sem要在共享記憶體中建立;
傳回值: 成功,傳回0;失敗,傳回-1,并置上errno;
減少信号量:sem_wait
sem_wait函數判斷信号量是否大于0,如果大于0,則将信号量減一,并且立即傳回,如果小于等于0,就阻塞在該函數,直到信号量大于0。
#include <semaphore.h>
int sem_wait(sem_t *sem);
sem: 待操作的信号量;
傳回值: 成功,傳回0;失敗,傳回-1,并置上errno
增加信号量:sem_post
sem_post用于給信号量加1
#include <semaphore.h>
int sem_post(sem_t *sem);
sem: 待操作的信号量;
傳回值: 成功,傳回0;失敗,傳回-1,并置上errno
删除信号量:sem_destroy
#include <semaphore.h>
int sem_destroy(sem_t *sem);
sem: 待操作的信号量;
傳回值: 成功,傳回0;失敗,傳回-1,并置上errno
代碼示例
線程1先被建立,但是阻塞在信号量上,線程2後被建立,被運作後将信号量增加,然後線程1識别到信号量大于零,才執行後面的步驟。
#include <semaphore.h>
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
sem_t sem;
void * func1(void *arg)
{
int ret;
ret = sem_wait(&sem);
if (ret != 0) {
perror("sem_wait: ");
return NULL;
}
printf("%s: pthread id: %ul\n", __func__, pthread_self());
}
void * func2(void *arg)
{
int ret;
printf("%s: pthread id: %ul\n", __func__, pthread_self());
ret = sem_post(&sem);
if (ret != 0) {
perror("sem_post: ");
return NULL;
}
}
int
main(int argc, char **argv)
{
int ret;
pthread_t p1, p2;
ret = sem_init(&sem, 0, 0);
if (ret < 0) {
perror("sem_init: ");
return -1;
}
ret = pthread_create(&p1, NULL, &func1, NULL);
if (ret != 0) {
perror("pthread_create: ");
return -1;
}
sleep(5);
ret = pthread_create(&p2, NULL, &func2, NULL);
if (ret != 0) {
perror("pthread_create: ");
return -1;
}
sleep(1);
return 0;
}
線程的互斥量
原理簡介:
- 互斥量底層也是通過鎖實作的,第一個線程通路互斥量的時候對互斥量加鎖,後續線程加鎖互斥量的時候會被阻塞,直到鎖被釋放
- 互斥量在POSIX中定義
- 互斥量是一種特殊的信号量,信号量是一個int數值,可以随意大小,互斥量隻有0和1
使用流程:
- 初始化互斥量
- 鎖住互斥量
- 解鎖互斥量
- 銷毀互斥量
初始化互斥量:pthread_mutex_init
互斥量用之前必須初始化:
//初始化方法1:使用預設屬性,必須在定義的時候初始化,不可以先定義後初始化
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
//初始化方法2:
#include <pthread.h>
int pthread_mutex_init(pthread_mutex_t *restrict mutex,
const pthread_mutexattr_t *restrict attr);
mutex: 待初始化的互斥量;
attr: 參數,可以直接使用NULL;
傳回值: 成功,傳回0,失敗,傳回非0,并置上errno
鎖住互斥量:pthread_mutex_lock
#include <pthread.h>
int pthread_mutex_lock(pthread_mutex_t *mutex);
mutex: 待鎖住的互斥量;
傳回值: 成功,傳回0,失敗,傳回非0,并置上errno
解鎖互斥量:pthread_mutex_unlock
#include <pthread.h>
int pthread_mutex_unlock(pthread_mutex_t *mutex);
mutex: 待解鎖的互斥量;
傳回值: 成功,傳回0,失敗,傳回非0,并置上errno;
銷毀互斥量:pthread_mutex_destroy
互斥量用完了之後要釋放
#include <pthread.h>
int pthread_mutex_destroy(pthread_mutex_t *mutex);
mutex: 待銷毀的互斥量;
傳回值: 成功,傳回0,失敗,傳回非0,并置上errno;
代碼示例
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void * func1(void *arg)
{
int ret;
ret = pthread_mutex_lock(&mutex);
if (ret != 0){
perror("pthread_mutex_lock: ");
return NULL;
}
printf("%s: pthread id: %ul\n", __func__, pthread_self());
pthread_mutex_destroy(&mutex);
}
void * func2(void *arg)
{
int ret;
printf("%s: pthread id: %ul\n", __func__, pthread_self());
}
int
main(int argc, char **argv)
{
int ret;
pthread_t p1, p2;
//ret = pthread_mutex_init(&mutex, NULL);
//if (ret != 0) {
// perror("pthread_mutex_init: ");
// return -1;
//}
ret = pthread_mutex_lock(&mutex);
if (ret != 0){
perror("pthread_mutex_lock: ");
return -1;
}
ret = pthread_create(&p1, NULL, &func1, NULL);
if (ret != 0) {
perror("pthread_create: ");
return -1;
}
sleep(5);
ret = pthread_create(&p2, NULL, &func2, NULL);
if (ret != 0) {
perror("pthread_create: ");
return -1;
}
sleep(1);
ret = pthread_mutex_unlock(&mutex);
if (ret != 0){
perror("pthread_mutex_lock: ");
return -1;
}
sleep(1);
return 0;
}