线程常用api

线程常用api

pthread_create

该api用于创建一个新线程

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void*(*start_routine)(void *), void *arg)
pthread_t *thread:指向线程标识符的指针,用于存储新创建的线程的线程标识符
const pthread_attr_t *attr:用来设置线程优先级、栈大小等属性,传入NULL时使用默认属性创建线程 
void*(*start_routine)(void *):一个指向函数的指针,定义了新线程执行的入口。该函数必须接受一个void*类型的参数,并返回void*类型的结果
void *arg:start_routine函数的参数,可以是一个指向任意类型数据的指针
return:成功返回0,失败返回非0    

例:

void *pthread_input(void *arg) {
    int i=0;
    while(1) {
        char c = fgetc(stdin);
        if(c && c != '\n') {
            buf[i++] = c;
            if(i > BUF_LEN) {
                i = 0;
            }
        }
    }
}
void *pthread_output(void *arg) {
    int i = 0;
    while(1) {
        if(buf[i]) {
            fputc(buf[i],stdout);
            buf[i++] = 0;
            if (i > BUF_LEN) {
                i = 0;
            }
        }
        else {
            sleep(1);
        }
    }
}
pthread_t pid_input,pid_output;
pthread_create(&pid_input,NULL,pthread_input,NULL);
pthread_create(&pid_output,NULL,pthread_output,NULL);

pthread_exit

该api用于关闭调用该方法的线程

void pthread_exit(void *retval)
void *retval:要返回给其他线程的数据    

pthread_join

该api用于等待指定线程结束,获取线程返回值并回收它的资源

int pthread_join(pthread_t thread, void **retval)
pthread_t thread:指定线程的线程id
void **retval:这是一个可选参数,用于接受线程结束后传递的返回值。
return:成功返回0,失败返回1    

例:

pthread_t pthid;
pthread_create(pthid,NULL,func,NULL);
pthread_join(pthid,NULL);

pthread_detach

该api用于在线程结束后自动回收该线程的资源,无需等待。

int pthread_detach(pthread_t thread)
pthread_t thread:要回收资源的线程id
return:成功返回0,失败返回错误码    

例:

pthread_t tid;
pthread_create(tid,NULL,func,NULL);
pthread_detach(tid);

pthread_cancel

该api用于终止指定线程

int pthread_cancel(pthread_t thread)
pthread_t thread:要终止线程的线程id
return:成功返回0,失败返回非0错误码    

例:

if (pthread_cancel(tid) != 0){
	perror("pthread_cancel");
}

pthread_setcancelstate

该api用于设置调用线程的取消状态

int pthread_setcancelstate(int state, int *oldstate)
int state:要设置的目标状态
int *oldstate:用于返回历史状态
return:成功返回0,失败返回非0错误码

int state目标状态如下:

1、PTHREAD_CANCEL_ENABLE:启用取消功能

2、PTHREAD_CANCEL_DISABLE:禁用取消功能

例:

void *func(void *arg) {
    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL);
    //该线程被设置为不可被取消
} 

pthread_setcanceltype

该api用于设置调用线程的取消类型

int pthread_setcanceltype(int type, int *oldtype)
int type:要设置的目标类型
int *oldtype:用于返回历史状态
return:成功返回0,失败返回非0错误码

int type目标类型如下:

1、PTHREAD_CANCEL_DEFERRED:设置取消类型为推迟

2、PTHREAD_CANCEL_ASYNCHRONOUS:设置取消类型为异步

推迟意味着取消请求会被挂起,直至被取消线程的执行取消点函数(pthread_testcancel)时才会真正执行线程的取消操作

异步意味着线程可能在任何时候被取消

例:

void *func(void *arg) {
    //默认取消类型为推迟,无需设置
    pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL);
    //该线程的取消类型被设置为异步
}

pthread_mutex_lock

该api用于给被调用的线程设置互斥锁,如果互斥锁已经被其他线程锁定,调用该api的线程将会被阻塞,直到互斥锁变为可用状态。

int pthread_mutex_lock(pthread_mutex_t *mutex)
pthread_mutex_t *mutex:锁
return:成功时返回0,失败是返回错误码    

例:

static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void *func(void *arg) {
    pthread_mutex_lock(&mutex);
}

pthread_mutex_trylock

该api用于尝试锁定指定的互斥锁,与pthread_mutex_lock不同,如果互斥锁已经被其他线程锁定,pthread_mutex_trylock不会阻塞调用线程,而是立即返回一个错误码(EBUSY)

int pthread_mutex_trylock(pthread_mutex_t *mutex)
pthread_mutex_t *mutex:锁
return:成功时返回0,失败是返回错误码       

例:

static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void *func(void *arg) {
    pthread_mutex_trylock(&mutex);
}

pthread_mutex_unlock

该api用于解锁指定的互斥锁。调用线程必须是当前持有互斥锁的线程,否则解锁操作可能会失败

int pthread_mutex_unlock(pthread_mutex_t *mutex)
pthread_mutex_t *mutex:锁
return:成功时返回0,失败是返回错误码  

例:

static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void *func(void *arg) {
    pthread_mutex_lock(&mutex);
    ...
    pthread_mutex_unlock(&mutex);
}

pthread_rwlock_init

该api用于为 rwlock 指向的读写锁分配所有需要的资源,并将锁初始化为未锁定状态。 读写锁的属性由 attr 参数指定,如果 attr 为 NULL,则使用默认属性。当锁的属性为默认时,可以通过宏 PTHREAD_RWLOCK_INITIALIZER 初始化

int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr)
pthread_rwlock_t *restrict rwlock:读写锁
const pthread_rwlockattr_t *restrict attr:读写锁的属性
return:成功返回0,失败返回错误码

restrict关键字表示该对象已经被指针所引用,不能通过除该指针外所有其他直接或间接的方式修改该对象的内容

例:

pthread_rwlock_t rwlock;
pthread_rwlock_init(&rwlock,NULL);

pthread_rwlock_destroy

该api用于销毁创建的读写锁,并释放它的所以资源

int pthread_rwlock_destroy(pthread_rwlock_t *rwlock)
pthread_rwlock_t *rwlock:读写锁    

例:

pthread_rwlock_t rwlock;
pthread_rwlock_init(&rwlock,NULL);
pthread_rwlock_destroy(&rwlock);

pthread_rwlock_rdlock

该api用于应用一个读锁到rwlock指向的读写锁上,并使调用线程获得读锁

int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock)
pthread_rwlock_t *rwlock:读写锁
return:成功返回0,失败返回错误码

例:

void *func(void *arg) {
	pthread_rwlock_rdlock(&rwlock);
}
pthread_rwlock_t rwlock;
pthread_rwlock_init(&rwlock,NULL);
pthread_rwlock_destroy(&rwlock);

pthread_rwlock_wrlock

该api用于应用一个写锁到 rwlock 指向的读写锁上,并使调用线程获得写锁

int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock)
pthread_rwlock_t *rwlock:读写锁
return:成功返回0,失败返回错误码    

例:

void *func(void *arg) {
	pthread_rwlock_wrlock(&rwlock);
}
pthread_rwlock_t rwlock;
pthread_rwlock_init(&rwlock,NULL);
pthread_rwlock_destroy(&rwlock);

pthread_rwlock_unlock

该api用于释放调用线程锁持有的 rwlock 指向的读写锁

int pthread_rwlock_unlock(pthread_rwlock_t *rwlock)
pthread_rwlock_t *rwlock:读写锁
return:成功返回0,失败返回错误码       

例:

void *func(void *arg) {
	pthread_rwlock_rdlock(&rwlock);
	pthread_rwlock_unlock(&rwlock);
}
pthread_rwlock_t rwlock;
pthread_rwlock_init(&rwlock,NULL);
pthread_rwlock_destroy(&rwlock);

pthread_rwlockattr_init

该api用于使用所有属性的默认值初始化 attr 指向的属性对象

int pthread_rwlockattr_init(pthread_rwlockattr_t *attr)
pthread_rwlockattr_t *attr:读写锁属性对象指针
return:成功时返回0,失败时返回错误码

例:

pthread_rwlockattr_t attr;
pthread_rwlockattr_init(&attr);

pthread_rwlockattr_destroy

该api用于销毁读写锁属性对象

int pthread_rwlockattr_destroy(pthread_rwlockattr_t *attr)
pthread_rwlockattr_t *attr:读写锁属性对象指针
return:成功时返回0,失败时返回错误码    

例:

pthread_rwlockattr_t attr;
pthread_rwlockattr_init(&attr);
pthread_rwlockattr_destroy(&attr);

pthread_rwlockattr_setkind_np

该api用于将 attr 指向的属性对象中的"锁类型"属性设置为 pref 规定的值

int pthread_rwlockattr_setkind_np(pthread_rwlockattr_t *attr, int pref)
pthread_rwlockattr_t *attr:读写锁属性对象指针
int pref:希望设置锁的类型
return:成功时返回0,失败时返回错误码  

int pref锁的类型可以被设置为以下三种取值模式中的其中一种:

1、PTHREAD_RWLOCK_PREFER_READER_NP: 默认值,读线程拥有更高优先级。当存在阻塞的写线程时,读线程仍然可以获得读写锁。只要不断有新的读线程,写线程将一直保持" 饥饿"

2、PTHREAD_RWLOCK_PREFER_WRITER_NP: 写线程拥有更高优先级。这一选项被 glibc 忽略

3、PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP: 写线程拥有更高优先级,在 当前系统环境下,它是有效的,将锁类型设置为该值以避免写饥饿

例:

pthread_rwlockattr_t attr;
pthread_rwlock_t rwlock;
pthread_rwlockattr_init(&attr);
pthread_rwlockattr_setkind_np(&attr,PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE);
pthread_rwlock_init(&rwlock,&attr);
pthread_rwlockattr_destroy(&attr);
pthread_rwlockattr_destroy(&rwlock);

pthread_cond_wait

该api用于阻塞当前线程并临时释放 mutex 锁,并等待其他线程调用 pthread_cond_signal 或 pthread_cond_broadcast 唤醒。被唤醒后该线程会尝试重新获取 mutex 锁。线程在被唤醒时,会从之前的阻塞处继续向下执行

int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex)
pthread_cond_t *restrict cond:指向条件变量的指针条件变量用于等待某个条件的发生。通过某一cond等待的线程需要通过同一cond的signal唤醒
pthread_mutex_t *restrict mutex:与条件变量配合使用的互斥锁的指针。在调用 pthread_cond_wait之前,线程必须已经获得了这个互斥锁
return:成功时返回0,失败时返回错误码    

例:

static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void *producer(void *arg) {
    int item = 1;
    while (1) {
        pthread_mutex_lock(&mutex);
        while(count == BUF_SIZE) {
            pthread_cond_wait(&cond,&mutex);
        }
        buf[count++] = item++;
        pthread_cond_signal(&cond);
        pthread_mutex_unlock(&mutex);
    }
}
void *consumer(void *arg) {
    while(1) {
        pthread_mutex_lock(&mutex);
        while(count == 0) {
            pthread_cond_wait(&cond,&mutex);
        }
        printf("%d",buf[--count]);
        pthread_cond_signal(&cond);
        pthread_mutex_unlock(&mutex);
    }
}
/*
该代码的执行流程是:
producer优先获得互斥锁,在获取到锁后向buf中写入数字,每写入5个,就会阻塞并且释放互斥锁。当producer阻塞并释放互斥锁后,consumer便成功获得互斥锁,并开始从buf中写出数据,每写出5个,就会阻塞并且释放互斥锁。当consumer阻塞并释放互斥锁后,producer便成功获得互斥锁。
*/

pthread_cond_timedwait

该api同pthread_cond_wait 相似,但是它添加了超时机制。如果在指定的 abstime 时间内条件变量没有被触发,函数将返回一个超时错误(ETIMEDOUT)

int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict abstime)
pthread_cond_t *restrict cond:指向条件变量的指针    
pthread_mutex_t *restrict mutex:与条件变量配合使用的互斥锁的指针
const struct timespec *restrict abstime:指向 timespec结构的指针,表示等待条件变量的绝对超时时间。timespec结构包含秒和纳秒两部分,指定了从某一固定点(如 UNIX 纪元,1970年1月1日)开始的时间
return:成功时返回 0;如果超时则返回 ETIMEDOUT;其他错误情况返回相应的错误码    

pthread_cond_signal

该api用于唤醒因cond而阻塞的线程,如果有多个因cond阻塞的线程,则随机唤醒一个。如果没有线程在等待,则什么也不做

int pthread_cond_signal(pthread_cond_t *cond)
pthread_cond_t *restrict cond:指向条件变量的指针
return:成功返回0,失败返回错误码    

pthread_cond_broadcast

该api用于唤醒所有因cond而阻塞的线程。如果没有线程在等待,则什么也不做

int pthread_cond_broadcast(pthread_cond_t *cond)
pthread_cond_t *restrict cond:指向条件变量的指针
return:成功返回0,失败返回错误码    

sem_init

该api用于在sem指向的地址初始化一个无名信号量

int sem_init(sem_t *sem, int pshared, unsigned int value)
sem_t *sem:信号量的地址
int pshared:指明信号量是线程间共享还是进程间共享
unsigned int value:信号量的初始值
return:成功返回0,失败返回EOF    

int pshared有两种取值:

1、0:信号量是线程间共享的,应该被置于所有线程均可见的地址(如,全局变量或在堆中动态分配的变量)

2、非0:信号量是在进程间共享的,应该被置于共享内存区域,任何进程只要能访问共享内存区域,即可操作进程间共享的信号量

例:

sem_t unnamedsem;
sem_init(&unnamedsem,0,1);

sem_destroy

该api用于销毁sem指向的无名信号量

int sem_destroy(sem_t *sem)
sem_t *sem:信号量的地址
return:成功返回0,失败返回EOF 

例:

sem_t unnamedsem;
sem_init(&unnamedsem,0,1);
sem_destroy(&unnamedsem);

sem_post

该api用于将 sem 指向的信号量加一,如果信号量从 0 变为 1,且其他进程或线程因信号量而阻塞,则阻塞的进程或线程会被唤醒并获取信号量,然后继续执行。POSIX 标准并未 明确定义唤醒策略,具体唤醒的是哪个进程或线程取决于操作系统的调度策略

int sem_post(sem_t *sem)
sem_t *sem:信号量的地址
return:成功返回0,失败返回EOF 

例:

void *plusOne(void *argv) {
	sem_wait(&unnamed_sem);
	int tmp = shard_num + 1;
	shard_num = tmp;
	sem_post(&unnamed_sem);
}

sem_wait

该api用于将 sem 指向的信号量减一。如果信号量的值大于 0,函数可以执行减一操作, 然后立即返回,调用线程继续执行。如果当前信号量的值是 0,则调用阻塞直至信号量的 值大于 0,或信号处理函数打断当前调用

int sem_wait(sem_t *sem)
sem_t *sem:信号量的地址
return:成功返回0,失败返回EOF 

sem_open

该api用于创建或打开一个已经存在的POSIX有名信号量

sem_t *sem_open(const char *name, int oflag,mode_t mode, unsigned int value)
const char *name:信号量的名称
int oflag:标记位,控制调用函数的行为。是一个或多个值或操作的结果。常用的是 O_CREAT
mode_t mode:有名信号量在临时文件系统中对应文件的权限。需要注意的是,应确保每个需要访问当前有名信号量的进程都可以获得读写权限
unsigned int value:信号量的初始值
return: 成功则返回创建的有名信号量的地址,失败则返回 SEM_FAILED,同时设置 errno以指出错误原因    

例:

char *sem_name = "/named_sem";
sem_t *sem = sem_open(sem_name,O_CREAT,0666,1);

sem_close

该api用于关闭对于sem指向有名信号量的引用

int sem_close(sem_t *sem)
sem_t *sem:有名信号量指针
return:成功返回0,失败返回EOF    

例:

char *sem_name = "/named_sem";
sem_t *sem = sem_open(sem_name,O_CREAT,0666,1);
sem_close(sem);

该api用于移除内存中的有名信号量对象,/dev/shm 下的有名信号量文件会被清除。当 没有任何进程引用该对象时才会执行清除操作。只应该执行一次

int sem_unlink(const char *name)
const char *name:信号量的名称 
return:成功返回0,失败返回EOF       

g_thread_pool_new

该api用于创建新的线程池

GThreadPool *g_thread_pool_new(GFunc func,gpointer user_data,gint max_threads,gboolean exclusive,GError **error);
GFunc func:线程池中执行的函数
gpointer user_data:传递给func的数据,可以为NULL
gint max_threads:线程池容量,即当前线程池中可以同时运行的线程数。-1表示没有限制
gboolean exclusive:独占标记位。决定当前线程池独占所有的线程还是和其他线程池共享这些线程
GError **error:用于报告错误信息,可以是NULL,表示忽略错误
return:GThreadPool *线程池实例指针。无论是否发生错误,都会返回有效的线程池

gboolean exclusive独占标记位的取值如下:

1、TRUE:立即启动数量为 max_threads 的线程,且启动的线程只能被当前线程池使用

2、FALSE:只有在需要时,即需要执行任务时才创建线程,且线程可以被多个非独享资源的线程池共用

g_thread_pool_push

该api用于向pool指定的线程池实例添加数据

gboolean g_thread_pool_push(GThreadPool *pool,gpointer data,GError **error)
GThreadPool *pool:指向线程池实例的指针
gpointer data:传递给每个任务的独享数据
GError **error:GError **error:用于报告错误信息,可以是NULL,表示忽略错误
return:成功返回true,失败返回false    

g_thread_pool_free

该api用于释放pool指向的线程池分配的所有资源

void g_thread_pool_free (GThreadPool* pool,gboolean immediate,gboolean wait_)
GThreadPool *pool:指向线程池实例的指针
gboolean immediate:是否立即释放线程池
gboolean wait_:当前函数是否阻塞等待所以任务完成    

gboolean immediate的取值如下:

1、TRUE:立即释放所有资源,未处理的数据不被处理

2、FALSE:在最后一个任务执行完毕之前,线程池不会被释放

需要注意的是:执行任务时,线程池的任何一个线程都不会被打断。无论这个参数是何取值,都可以保证至少线程池释放前正在运行的线程可以完成它们的任务。

gboolean wait_的取值如下:

1、TRUE:所有需要处理的任务执行完毕当前函数才会返回

2、FALSE:当前函数立即返回

posted @ 2024-08-21 11:38  Tacitle  阅读(1)  评论(0编辑  收藏  举报