引入头文件

#include <pthread.h>

接下来来看看具体的实际的用法

pthread_create

概念:创建一个线程

// td.cpp
#include <pthread.h>
#include <iostream>
void* fun(void* arg);
int main() {
pthread_t pid;
pthread_create(&pid, NULL, fun, NULL);
pthread_exit(0);
return 0;
}
void* fun(void* arg) {
std::cout << "a" << std::endl;
std::cout << pthread_self() << std::endl;
}

输出如下

a
140446322251520

pthread_self()

概念:获取线程ID

循环创建多个子线程

#include <pthread.h>
#include <iostream>

#define NUM_PTHREAD 5
void* fun(void* arg);

int main() {
pthread_t pid[NUM_PTHREAD];
for (int i = 0; i < NUM_PTHREAD; i++) {
pthread_create(&pid[i], NULL, fun, NULL);
}
pthread_exit(0);
return 0;
}
void* fun(void* arg) {
// std::cout << "a" << std::endl;
std::cout << pthread_self() << std::endl;
}

输出如下

140343301449472
140343293056768
140343276271360
140343284664064
140343267878656

pthread_exit

pthread_exit(pthread_t *pid, void *status);

  • pid:线程ID的地址
  • statue:线程退出状态(传入值)

概念:将单个线程退出

注意一点:exit是将进程退出,此时所有的子线程都要退出了

pthread_join

pthread_join(pthread_t pid, void** status);

  • pid:线程ID
  • status:获取线程退出的状态

概念:回收子线程,阻塞等待线程退出,获取线程当前状态

#include <iostream>
#include <pthread.h>


typedef struct
{
int m_a;
int m_b;
}mm;
void* fun(void* arg)
{
mm* m;
m->m_a = 1;
m->m_b = 2;
// 线程退出状态为一个m结构体,此处m是指针类型
pthread_exit((void*)m);
}
int main()
{
mm* m;
pthread_t pid;
int ret = pthread_create(&pid, NULL, fun, NULL);
if (ret != 0) {
std::cout << "create a thread failed" << std::endl;
exit(1);
}
// 因为线程退出状态是指针类型,因此此处要获取他的地址,即解引用
pthread_join(pid, (void**)&m);

std::cout << "n is: " << m->m_a << m->m_b << std::endl;
pthread_exit(0);
}

pthread_detach

pthread_detach(pthread_t pid);

  • pid:线程ID

概念:线程分离,将主线程和子线程进行分离,子线程不受主线程退出的影响,成功返回0,失败返回错误号

#include <iostream>
#include <pthread.h>

void* func(void*);
int main()
{
pthread_t pid;
int ret;

ret = pthread_create(&pid, NULL, func, NULL);
if (ret != 0) {
std::cout << "create failed" << std::endl;
}
pthread_exit(0);
return 0;
}
void* func(void* arg)
{
int ret = pthread_detach(pthread_self());
std::cout << "hello linux" << std::endl;
pthread_exit((void*)1);
}

pthread_cancel

pthread_cancel(pthread_t pid)

概念: 杀死线程,对应进程中的kill函数

注意:线程的杀死不是实时的,有一定时间的延迟,要等到一定的检查点才开始杀除(write,read等等)

void* func(void* arg) 
{
while(1)
{
// 自己添加取消点
pthread_testcancel();
}
}

线程同步,线程互斥

概念性东西都是一样的,可以去看看我之前写的在Windows下的线程同步和互斥

互斥量mutex

每个线程在对资源操作前都尝试先加锁,成功后加锁才能成功,操作结束解锁,资源还是共享的,线程间也还是竞争的,但通过所就将资源的访问变成互斥操作,而后与时间有关的错误也不会再发生了(一个时间只能有一个线程在访问资源)
主要应用函数

pthread_mutex_x:本质是一个结构体,加锁成功返回1,解锁成功返回0

pthread_mutex_init:初始化一个互斥锁(互斥量),初值可看成1,

int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t* restrict attr);

pthread_mutex_lock:加锁操作后mutex值变成0

pthread_mutex_unlock:解锁操作后mutex变成1

pthread_destroy:销毁一个互斥量

pthread_mutex_trylock:一个线程抢到了共享资源就用,抢不到就不抢了

死锁

  • 一个线程加两个锁
  • 两个线程都加锁访问共享资源

读写锁

读写锁也叫共享-独占锁,当读写锁以读模式锁住时,他是以共享模式锁住的,当他以写模式锁住时,他是以共享模式锁住的,其中,写锁优先级高

主要应用函数(含义同上)

  • pthread_rwloakc_init
  • pthread_rwlock_destroy
  • pthread_rwlock_rdlock
  • pthread_rwlock_wrlock
  • pthread_rwlock_tryrdlock
  • pthread_rwlock_trywrlock
  • pthread_rwlock_unlock