多线程

线程函数

以下函数包含在头文件 pthread.h

线程ID

每一个线程都有一个唯一的线程ID,ID类型为pthread_t,是一个无符号长整形数,这个函数用于返回线程ID

pthread_t pthread_self(void);
  • 返回值:当前线程ID

创建线程

int pthread_create(pthread_t * thread, const pthread_attr_t* attr, void * (*start_routine)(void*), void* arg);
  • thread:传出参数,线程创建成功后会将线程id写入这个指针指向的内存
  • attr:线程属性,一般情况下默认即可,写NULL
  • start_routine:函数指针,该函数会在子线程中执行,类似于子线程的main函数,要求函数是静态函数
  • argstart_routine指向的函数的参数
  • 返回值:创建成功返回0,失败则返回对应错误号

线程退出

这个函数用于线程的退出,但是不会释放地址空间,只要调用该函数线程立刻退出,不会影响其他线程的运行

void pthread_exit(void *retval);
  • retval:线程退出时携带的数据,当前子线程的主线程会得到该数据,不需要使用写NULL即可

线程回收

这个函数是阻塞函数,如果还有子线程在运行,调用该函数就会阻塞,子线程退出函数解除阻塞进行资源的回收,所以完整的线程关闭即要子线程自己退出,也要主线程来回收子线程资源
该函数被调用一次,只能回收一个子线程,如果有多个子线程则需要循环进行回收

int pthread_join(pthread_t thread, void **retval);
  • thread:要回收的线程的ID
  • retval:传出参数,指向一级指针,一级指针指向一块内存,内存中存储了pthread_exit()传出的数据。不需要写NULL即可

线程脱离

将线程设置成脱离态(detached)后,当这一线程运行结束时,它的资源会被系统自动回收,而不再需要在其它线程中对其进行 pthread_join() 操作

int pthread_detach(pthread_t thread);

互斥锁

多用于线程同步
设想这样一种情况,我们创建了两个线程,他们的任务就是把变量i从0加到100,线程A把变量i从3加到了4,还没来得及把数据写回物理内存,CPU时间片就被线程B抢走了,线程B从物理内存里取出的变量i还没被线程A更新,这就导致线程A白数了一次,降低了效率。
image
这种情况不仅会降低效率,有时甚至会引发数据混乱,造成错误。
我们不希望这种情况发生,即不希望多个线程同时操作一个资源,我们就可以用到互斥锁。

以下函数包含在头文件 pthread.h

创建一把互斥锁

pthread_mutex_t  mutex;

在创建的锁对象中保存了当前这把锁的状态信息:锁定还是打开,如果是锁定状态还记录了给这把锁加锁的线程ID

初始化互斥锁

int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);
  • mutex:需要初始化的互斥锁
  • attr:互斥锁的属性,一般设置为NULL即可

上锁和解锁

  • 上锁(阻塞)
    当锁不空闲,调用这个函数的线程就会挂起等待,直到自己抢到了锁并上锁
int pthread_mutex_lock(pthread_mutex_t *mutex);
  • 上锁(非阻塞)
    当锁不空闲,这个函数会直接返回EBUSY,如果锁空闲,那么自己就加锁
int pthread_mutex_trylock(pthread_mutex_t *mutex);
  • 解锁
    由抢到了锁并上锁的线程来调用,把锁解开
int pthread_mutex_unlock(pthread_mutex_t *mutex);

释放互斥锁资源

int pthread_mutex_destroy(pthread_mutex_t *mutex);

信号量

多用于线程同步
信号量类型是sem_t

sem_t sem;

初始化信号量

int sem_init (sem_t *sem, int pshared, unsigned int value);

参数一是要被初始化的信号量,后两个参数不用关心,填0

信号量加一

int sem_post(sem_t * sem);

将信号量加一

信号量减一

int sem_wait(sem_t * sem);

当信号量大于0时,将信号量减一,当信号量等于0时,将调用此函数的线程阻塞,直到信号量大于0,并将信号量减一
反正就是横竖都要把信号量减一

销毁信号量

int sem_destroy(sem_t *sem);
posted @ 2023-08-27 22:22  悲伤鳄鱼吃面包  阅读(22)  评论(0编辑  收藏  举报