#include
int pthread_create(
pthread_t *thread, // 线程标识符(输出参数)
const pthread_attr_t *attr, // 线程属性(通常设为 NULL)
void *(*start_routine)(void *), // 线程入口函数
void *arg // 传递给线程函数的参数
);
//成功返回 0,失败返回错误码(非 errno,需用 strerror 解析)
//编译时需要加上 -pthread选项
参数 | 说明 |
---|---|
thread |
指向 pthread_t 的指针,用于存储新线程的 ID。 |
attr |
线程属性(如栈大小、调度策略等),通常设为 NULL (默认属性)。 |
start_routine |
线程的入口函数,必须是 void* func(void*) 形式。 |
arg |
传递给 start_routine 的参数(可以是任意类型,需强制转换),可填NULL。 |
//单线程
#include
#include
#include
// 线程函数
void* thread_task(void *arg) {
int num = *(int *)arg;
printf("这是分支线程%d\n", num);
sleep(1);
return NULL;
}
int main() {
pthread_t tid;
int num = 42;
// 创建线程
if (pthread_create(&tid, NULL, thread_task, &num) != 0) {
perror("pthread_create failed");
return 1;
}
sleep(1);// 等待分支线程结束
printf("Main thread exits\n");
return 0;
}
/*
输出:
这是分支线程42
Main thread exits
*/
//多线程
#include
#include
#include
#define NUM_THREADS 5
void* thread_func(void *arg) {
int id = *(int *)arg;
printf("Thread %d is running\n", id);
return NULL;
}
int main() {
pthread_t threads[NUM_THREADS];
int thread_args[NUM_THREADS];
for (int i = 0; i < NUM_THREADS; i++) {
thread_args[i] = i;
if (pthread_create(&threads[i], NULL, thread_func, &thread_args[i]) != 0) {
perror("pthread_create failed");
return 1;
}
}
sleep(2);//等待分支进程结束
printf("All threads finished\n");
return 0;
}
/*
输出:
Thread 0 is running
Thread 1 is running
Thread 2 is running
Thread 3 is running
Thread 4 is running
All threads finished
*/
//向线程中传入多个数据
#include
#include
// 定义信息结构体,用于向线程传递数据
typedef struct {
int num;
char name[20];
double score;
} Info;
// 线程函数
void *task(void *arg) {
Info buf = *((Info*)arg); // 解引用获取结构体副本
printf("子线程中:num = %d, name = %s, score = %.2lf\n",
buf.num, buf.name, buf.score);
return NULL;
}
int main(int argc, const char *argv[]) {
pthread_t tid;
Info buf = {
.num = 520,
.name = "zhangsan",
.score = 99.5
};
// 创建线程
if (pthread_create(&tid, NULL, task, &buf) != 0) {
perror("线程创建失败");
return 1;
}
printf("线程创建成功,tid = 0x%lx\n", (unsigned long)tid);
printf("主线程运行中...\n");
// 等待子线程结束(避免主线程直接退出)
sleep(2);
return 0;
}
#include
pthread_t pthread_self(void);
//功能:获取当前线程的线程号
//参数:无
//返回值:返回调用线程的id号,不会失败
#include
void pthread_exit(void *retval);
//功能:退出当前线程
//参数:表示退出时的状态,一般填NULL
//返回值:无
#include
int pthread_join(pthread_t thread, void **retval);
/*
功能:阻塞回收指定线程的资源
参数1:要回收的线程线程号
参数2:线程退出时的状态,一般填NULL
返回值:成功返回0,失败返回一个错误码
*/
#include
int pthread_detach(pthread_t thread);
/*
功能:将指定线程设置成分离态,被设置成分离态的线程,退出后,资源由系统自动回收
参数:要分离的线程号
返回值:成功返回0,失败返回一个错误码
*/
//示例
#include
#include
#include
// 线程函数
void* task(void* arg) {
printf("子线程 ID: 0x%lx\n", (unsigned long)pthread_self());
sleep(3);
pthread_exit(nullptr); // 显式退出线程
}
int main() {
pthread_t tid;
// 创建线程
if (pthread_create(&tid, nullptr, task, nullptr) != 0) {
perror("线程创建失败");
return EXIT_FAILURE;
}
printf("主线程中 - 子线程 ID: 0x%lx\n", (unsigned long)tid);
// 设置线程为分离状态(非阻塞)
if (pthread_detach(tid) != 0) {
perror("线程分离失败");
return EXIT_FAILURE;
}
sleep(5); // 主线程等待足够时间让子线程完成
std::cout << "主线程结束" << std::endl;
return EXIT_SUCCESS;
}
//使用多线程完成两个文件的拷贝,线程1拷贝前一半内容,线程2拷贝后一半内容,主线程用于回收两个分支线程的资源
#include
#include
#include
#include
#include
#include
// 定义要向线程体函数中传递数据的结构体类型
struct Info {
const char *srcfile; // 要拷贝的原文件
const char *destfile; // 目标文件
int start; // 起始位置
int len; // 要拷贝的长度
};
// 定义获取文件长度的函数
int get_file_len(const char *srcfile, const char *destfile)
{
// 定义两个文件描述符,分别作为源文件和目标文件的句柄
int sfd, dfd;
// 以只读的形式打开源文件
if ((sfd = open(srcfile, O_RDONLY)) == -1) {
perror("open srcfile error");
return -1;
}
// 以只写的形式打开目标文件
if ((dfd = open(destfile, O_RDWR|O_CREAT|O_TRUNC, 0664)) == -1) {
perror("open destfile error");
return -1;
}
// 获取源文件的长度
int len = lseek(sfd, 0, SEEK_END);
// 关闭文件
close(sfd);
close(dfd);
return len;
}
// 定义线程体函数
void *task(void *arg)
{
// 将传入的数据解析出来
const char *srcfile = ((struct Info*)arg)->srcfile;
const char *destfile = ((struct Info*)arg)->destfile;
int start = ((struct Info*)arg)->start;
int len = ((struct Info*)arg)->len;
// 准备拷贝工作
// 定义两个文件描述符,分别作为源文件和目标文件的句柄
int sfd, dfd;
// 以只读的形式打开源文件
if ((sfd = open(srcfile, O_RDONLY)) == -1) {
perror("open srcfile error");
return NULL;
}
// 以只写的形式打开目标文件
if ((dfd = open(destfile, O_RDWR)) == -1) {
perror("open destfile error");
return NULL;
}
// 偏移指针
lseek(sfd, start, SEEK_SET);
lseek(dfd, start, SEEK_SET);
// 拷贝工作
int ret = 0; // 记录每次读取的数据
int count = 0; // 记录拷贝的总个数
char buf[128] = ""; // 数据搬运工
while (1) {
ret = read(sfd, buf, sizeof(buf));
// 将读取的数据放入到count中
count += ret;
if (count >= len) {
// 说明该部分的内容拷贝结束,还剩最后一次
write(dfd, buf, ret - (count - len));
break;
}
// 其余的正常拷贝
write(dfd, buf, ret);
}
// 关闭文件描述符
close(dfd);
close(sfd);
}
int main(int argc, const char *argv[])
{
// 判断传入的文件个数是否正确
if (argc != 3) {
printf("input file error\n");
printf("usage:./a.out srcfile destfile\n");
return -1;
}
// 获取原文件的长度,顺便将目标文件创建出来
int len = get_file_len(argv[1], argv[2]);
// 创建两个线程
pthread_t tid1, tid2;
// 定义向线程体函数传参的变量
struct Info buf[2] = {
{argv[1], argv[2], 0, len/2},
{argv[1], argv[2], len/2, len - len/2}
};
if (pthread_create(&tid1, NULL, task, &buf[0]) != 0) {
printf("线程创建失败\n");
return -1;
}
if (pthread_create(&tid2, NULL, task, &buf[1]) != 0) {
printf("线程创建失败\n");
return -1;
}
// 主线程中完成对两个分支线程资源的回收
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
printf("拷贝成功\n");
std::cout << "Hello, World!" << std::endl;
return 0;
}
当多个线程共享资源时,可能出现:
互斥锁的本质也是一个特殊的临界资源,当该临界资源被某个线程所拥有后,其他线程就不能拥有该资源,直到,拥有该资源的线程释放掉互斥锁后,其他线程才能进行抢占(同一时刻,一个互斥锁只能被一个线程所拥有)
基本用法:
//创建互斥锁:定义一个个pthread_mutex_t 类型的变量即创建了一个互斥锁
//初始化互斥锁
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;//静态初始化
int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);
/*
功能:初始化互斥锁变量
参数1:互斥锁变量的地址,属于地址传递
参数2:互斥锁属性,一般填NULL,让系统自动设置互斥锁属性
返回值:成功返回0,失败返回错误码
*/
//获取锁资源
int pthread_mutex_lock(pthread_mutex_t *mutex); /*
功能:获取锁资源,如果要获取的互斥锁已经被其他线程锁定,那么该函数会阻塞,直到能够获取锁资源
参数:互斥锁地址,属于地址传递
返回值:成功返回0,失败返回一个错误码
*/
//释放锁资源
int pthread_mutex_unlock(pthread_mutex_t *mutex);
/*
功能:释放对互斥锁资源的拥有权
参数:互斥锁变量的地址
返回值:成功返回0,失败返回一个错误码
*/
//销毁互斥锁
int pthread_mutex_destroy(pthread_mutex_t *mutex);
/*
功能:销毁互斥锁
参数:互斥锁变量的地址
返回值:成功返回0,失败返回一个错误码
*/
特点:
示例:
#include
#include
#include
// 全局互斥锁
pthread_mutex_t mutex;
// 共享资源
int num = 520;
// 线程1:每次减少10
void* task1(void* arg) {
while (1) {
sleep(1);
pthread_mutex_lock(&mutex);
num -= 10;
printf("张三取了10,剩余%d\n", num);
pthread_mutex_unlock(&mutex);
}
return nullptr;
}
// 线程2:每次减少20
void* task2(void* arg) {
while (1) {
sleep(1);
pthread_mutex_lock(&mutex);
num -= 20;
printf("李四取了20,剩余%d\n", num);
pthread_mutex_unlock(&mutex);
}
return nullptr;
}
int main() {
// 初始化互斥锁
pthread_mutex_init(&mutex, nullptr);
// 创建线程
pthread_t tid1, tid2;
if (pthread_create(&tid1, nullptr, task1, nullptr) != 0) {
std::cerr << "线程1创建失败" << std::endl;
return 1;
}
if (pthread_create(&tid2, nullptr, task2, nullptr) != 0) {
std::cerr << "线程2创建失败" << std::endl;
return 1;
}
printf("主线程:tid1 = 0x%lx, tid2 = 0x%lx\n",
(unsigned long)tid1, (unsigned long)tid2);
// 等待线程结束(实际不会执行到,因线程是无限循环)
pthread_join(tid1, nullptr);
pthread_join(tid2, nullptr);
// 销毁互斥锁
pthread_mutex_destroy(&mutex);
std::cout << "程序结束" << std::endl;
return 0;
}
/*
输出:
主线程:tid1 = 0x2, tid2 = 0x3
张三取了10,剩余510
李四取了20,剩余490
张三取了10,剩余480
李四取了20,剩余460
张三取了10,剩余450
李四取了20,剩余430
张三取了10,剩余420
李四取了20,剩余400
张三取了10,剩余390
李四取了20,剩余370
张三取了10,剩余360
...
*/
概念
读写锁是一种特殊的同步机制,它允许多个线程同时读取共享资源,但只允许一个线程写入资源,非常适合读多写少的场景。
基本用法:
//初始化
pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER; // 静态初始化
pthread_rwlock_init(&rwlock, NULL);//动态初始化
/*
功能:初始化锁变量
参数1:锁变量的地址,属于地址传递
参数2:锁属性,一般填NULL,让系统自动设置互斥锁属性
返回值:成功返回0,失败返回错误码
*/
//读锁定(共享锁)
pthread_rwlock_rdlock(&rwlock); // 阻塞获取读锁
pthread_rwlock_tryrdlock(&rwlock); // 非阻塞尝试获取读锁
//写锁定(独占锁)
pthread_rwlock_wrlock(&rwlock); // 阻塞获取写锁
pthread_rwlock_trywrlock(&rwlock); // 非阻塞尝试获取写锁
//解锁
pthread_rwlock_unlock(&rwlock); // 释放读写锁
//销毁
pthread_rwlock_destroy(&rwlock);
特点:
示例
#include
#include
#include
#include
pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;
std::vector<int> shared_data; // 共享数据
void* reader(void* arg) {
int id = *(int*)arg; // 获取读者 ID
while (true) {
pthread_rwlock_rdlock(&rwlock);
std::cout << "Reader " << id << " sees: ";
for (int num : shared_data) {
std::cout << num << " ";
}
std::cout << std::endl;
pthread_rwlock_unlock(&rwlock);
sleep(1);
}
return nullptr;
}
void* writer(void* arg) {
int id = *(int*)arg; // 获取写者 ID
int count = 0;
while (true) {
pthread_rwlock_wrlock(&rwlock);
shared_data.push_back(++count);
std::cout << "Writer " << id << " added " << count << std::endl;
pthread_rwlock_unlock(&rwlock);
sleep(2);
}
return nullptr;
}
int main() {
const int NUM_READERS = 3;
const int NUM_WRITERS = 1;
pthread_t readers[NUM_READERS], writers[NUM_WRITERS];
int readers_id[NUM_READERS],writers_id[NUM_WRITERS];
// 创建读者线程
for (int i = 0; i < NUM_READERS; ++i) {
readers_id[i] = i;
pthread_create(&readers[i], NULL, reader, &readers_id[i]);
}
// 创建写者线程
for (int i = 0; i < NUM_WRITERS; ++i) {
writers_id[i] = i;
pthread_create(&writers[i], NULL, writer, &writers_id[i]);
}
// 等待线程
for (int i = 0; i < NUM_READERS; ++i) {
pthread_join(readers[i], NULL);
}
for (int i = 0; i < NUM_WRITERS; ++i) {
pthread_join(writers[i], NULL);
}
pthread_rwlock_destroy(&rwlock);
return 0;
}
概念:条件变量是线程同步的重要机制,它与互斥锁配合使用可以实现复杂的线程同步需求:
broadcast
)和单播(signal
)两种唤醒方式基本用法:
//定义和初始化
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;// 静态初始化(推荐)
pthread_cond_t cond;
pthread_cond_init(&cond, NULL);// 动态初始化
int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *restrict attr);
/*
功能:初始化条件变量
参数1:条件变量的起始地址
参数2:条件变量的属性,一般填NULL
返回值:成功返回0,失败返回一个错误码
*/
//等待条件
int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex);
/*
功能:将线程放入休眠等待队列,等待其他线程的唤醒
参数1:条件变量的地址
参数2:互斥锁,由于多个消费者线程进入等待队列时会产生竞态,为了解决竞态,需要使用一个互斥锁
返回值:成功返回0,失败返回错误码
*/
//通知条件
int pthread_cond_broadcast(pthread_cond_t *cond);
/*
功能:唤醒条件变量维护的队列中的所有消费者线程
参数:条件变量的地址
返回值:成功返回0,失败返回错误码
*/
int pthread_cond_signal(pthread_cond_t *cond);
/*
功能:唤醒条件变量维护的队列中的第一个进入队列的消费者线程
参数:条件变量的地址
返回值:成功返回0,失败返回错误码
*/
//销毁条件变量
int pthread_cond_destroy(pthread_cond_t *cond);
/*
功能:销毁一个条件变量
参数:条件变量的地址
返回值:成功返回0,失败返回错误码
*/
特点:
示例
#include
#include
#include
// 定义条件变量和互斥锁
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
// 生产者线程
void* producer(void* arg) {
sleep(3); // 模拟生产过程耗时
std::cout << "生产者(" << pthread_self() << "): 生产了3辆小米su7" << std::endl;
// 唤醒所有消费者线程
pthread_cond_broadcast(&cond);
pthread_exit(nullptr);
}
// 消费者线程
void* consumer(void* arg) {
// 获取互斥锁
pthread_mutex_lock(&mutex);
// 等待条件变量通知
pthread_cond_wait(&cond, &mutex);
std::cout << "消费者(" << pthread_self() << "): 消费了一辆小米su7,很开心" << std::endl;
// 释放互斥锁
pthread_mutex_unlock(&mutex);
pthread_exit(nullptr);
}
int main() {
// 创建线程
pthread_t tid_producer, tid_consumer1, tid_consumer2, tid_consumer3;
// 创建1个生产者线程
if (pthread_create(&tid_producer, nullptr, producer, nullptr) != 0) {
std::cerr << "生产者线程创建失败" << std::endl;
return EXIT_FAILURE;
}
// 创建3个消费者线程
if (pthread_create(&tid_consumer1, nullptr, consumer, nullptr) != 0 ||
pthread_create(&tid_consumer2, nullptr, consumer, nullptr) != 0 ||
pthread_create(&tid_consumer3, nullptr, consumer, nullptr) != 0) {
std::cerr << "消费者线程创建失败" << std::endl;
return EXIT_FAILURE;
}
// 打印线程ID
std::cout << "主线程: "
<< "生产者=" << tid_producer
<< ", 消费者1=" << tid_consumer1
<< ", 消费者2=" << tid_consumer2
<< ", 消费者3=" << tid_consumer3 << std::endl;
// 等待所有线程结束
pthread_join(tid_producer, nullptr);
pthread_join(tid_consumer1, nullptr);
pthread_join(tid_consumer2, nullptr);
pthread_join(tid_consumer3, nullptr);
// 销毁条件变量和互斥锁
pthread_cond_destroy(&cond);
pthread_mutex_destroy(&mutex);
std::cout << "程序运行结束" << std::endl;
return EXIT_SUCCESS;
}
/*
运行结果:
主线程: 生产者=2, 消费者1=3, 消费者2=4, 消费者3=5
生产者(2): 生产了3辆小米su7
消费者(5): 消费了一辆小米su7,很开心
消费者(3): 消费了一辆小米su7,很开心
消费者(4): 消费了一辆小米su7,很开心
程序运行结束
*/
基本概念
基本用法:
#include
//定义信号量
sem_t sem; // 定义无名信号量变量
//初始化信号量
int sem_init(sem_t *sem, int pshared, unsigned int value);
/*
初始化无名信号量,最主要是初始化value值
sem:信号量地址
pshared:0表示线程间同步,非0表示进程间同步
value:信号量初始值
返回值:成功返回0,失败返回-1
*/
//申请资源
int sem_wait(sem_t *sem);
/*
功能:阻塞申请无名信号量中的资源,成功申请后,会将无名信号量的value进行减1操作,如果当前无名信号量的value为0,则阻塞
参数:无名信号量的地址
返回值:成功返回0,失败返回-1并置位错误码
*/
//释放资源
int sem_post(sem_t *sem);
/*
功能:将无名信号量的value值增加1操作
参数:无名信号量地址
返回值:成功返回0,失败返回-1并置位错误码
*/
//销毁资源
int sem_destroy(sem_t *sem);
/*
功能:销毁无名信号量
参数:无名信号量地址
返回值:成功返回0,失败返回-1并置位错误码
*/
特点:
示例
#include
#include
#include
#include
// 定义无名信号量
sem_t sem;
// 生产者线程
void* producer(void* arg) {
int num = 5;
while (num--) {
sleep(1);
printf("生产者:生产了一辆小米su7\n");
// 释放信号量资源(V操作)
sem_post(&sem);
}
pthread_exit(nullptr);
}
// 消费者线程
void* consumer(void* arg) {
int num = 5;
while (num--) {
// 申请信号量资源(P操作)
sem_wait(&sem);
printf("消费者:消费了一辆小米su7,很开心\n");
}
pthread_exit(nullptr);
}
int main() {
// 初始化无名信号量
// 参数1: 信号量指针
// 参数2: 0表示线程间共享
// 参数3: 初始值0表示初始无资源
sem_init(&sem, 0, 0);
// 创建生产者消费者线程
pthread_t tid_producer, tid_consumer;
if (pthread_create(&tid_producer, nullptr, producer, nullptr) != 0) {
std::cerr << "生产者线程创建失败" << std::endl;
return EXIT_FAILURE;
}
if (pthread_create(&tid_consumer, nullptr, consumer, nullptr) != 0) {
std::cerr << "消费者线程创建失败" << std::endl;
return EXIT_FAILURE;
}
// 打印线程ID(使用标准格式)
printf("主线程:生产者tid = 0x%lx, 消费者tid = 0x%lx\n",
(unsigned long)tid_producer,
(unsigned long)tid_consumer);
// 等待线程结束
pthread_join(tid_producer, nullptr);
pthread_join(tid_consumer, nullptr);
// 销毁无名信号量
sem_destroy(&sem);
std::cout << "程序运行结束" << std::endl;
return EXIT_SUCCESS;
}
/*
代码运行结果:
主线程:生产者tid = 0x2, 消费者tid = 0x3
生产者:生产了一辆小米su7
消费者:消费了一辆小米su7,很开心
生产者:生产了一辆小米su7
消费者:消费了一辆小米su7,很开心
生产者:生产了一辆小米su7
消费者:消费了一辆小米su7,很开心
生产者:生产了一辆小米su7
消费者:消费了一辆小米su7,很开心
生产者:生产了一辆小米su7
消费者:消费了一辆小米su7,很开心
程序运行结束
*/
案例
//练习:使用无名信号量完成,定义三个任务,任务1打印A,任务2打印B,任务3打印C,最终输出的结果为ABCABCABCABC...
#include
#include
#include
#include
// 定义三个无名信号量
sem_t sem1, sem2, sem3;
// 打印A的线程
void* taskA(void* arg) {
while (true) {
sem_wait(&sem1); // 等待sem1
sleep(1);
std::cout << "A" << std::flush;
sem_post(&sem2); // 释放sem2
}
return nullptr;
}
// 打印B的线程
void* taskB(void* arg) {
while (true) {
sem_wait(&sem2); // 等待sem2
sleep(1);
std::cout << "B" << std::flush;
sem_post(&sem3); // 释放sem3
}
return nullptr;
}
// 打印C的线程
void* taskC(void* arg) {
while (true) {
sem_wait(&sem3); // 等待sem3
sleep(1);
std::cout << "C" << std::flush;
sem_post(&sem1); // 释放sem1
}
return nullptr;
}
int main() {
// 初始化信号量
sem_init(&sem1, 0, 1); // sem1初始为1,让A先执行
sem_init(&sem2, 0, 0);
sem_init(&sem3, 0, 0);
// 创建三个线程
pthread_t tidA, tidB, tidC;
if (pthread_create(&tidA, nullptr, taskA, nullptr) != 0) {
std::cerr << "线程A创建失败" << std::endl;
return EXIT_FAILURE;
}
if (pthread_create(&tidB, nullptr, taskB, nullptr) != 0) {
std::cerr << "线程B创建失败" << std::endl;
return EXIT_FAILURE;
}
if (pthread_create(&tidC, nullptr, taskC, nullptr) != 0) {
std::cerr << "线程C创建失败" << std::endl;
return EXIT_FAILURE;
}
// 等待线程结束(实际上不会执行到这里)
pthread_join(tidA, nullptr);
pthread_join(tidB, nullptr);
pthread_join(tidC, nullptr);
// 销毁信号量(实际不会执行到这里)
sem_destroy(&sem1);
sem_destroy(&sem2);
sem_destroy(&sem3);
return EXIT_SUCCESS;
}
概念:屏障(barrier)是一种线程同步机制,它允许多个线程在某个执行点相互等待,直到所有参与的线程都到达该点后才能继续执行。
基本用法:
//初始化屏障
int pthread_barrier_init(pthread_barrier_t *barrier, const pthread_barrierattr_t *attr,unsigned int count);
/*
barrier: 屏障对象指针
attr: 屏障属性(通常为NULL)
count: 需要等待的线程数量
返回值:成功返回0,失败返回错误码
*/
//等待屏障
int pthread_barrier_wait(pthread_barrier_t *barrier);
/*
线程调用此函数将阻塞,直到足够数量的线程到达屏障
最后一个到达的线程会唤醒所有等待线程
返回值:对最后一个到达的线程返回PTHREAD_BARRIER_SERIAL_THREAD
其他线程返回0
失败返回错误码
*/
//销毁屏障
int pthread_barrier_destroy(pthread_barrier_t *barrier);
特点
示例
#include
#include
#include
#define THREAD_NUM 3
pthread_barrier_t barrier;
void* task(void* arg) {
long id = *(long*)arg;
std::cout << "线程" << id << "开始执行第一阶段" << std::endl;
sleep(id + 1); // 模拟不同耗时
// 等待所有线程到达屏障
int ret = pthread_barrier_wait(&barrier);
if (ret == PTHREAD_BARRIER_SERIAL_THREAD) {
std::cout << "所有线程已到达屏障,最后一个线程是" << id << std::endl;
}
std::cout << "线程" << id << "开始执行第二阶段" << std::endl;
return nullptr;
}
int main() {
pthread_t threads[THREAD_NUM];
long threads_id[THREAD_NUM];
// 初始化屏障,等待3个线程
pthread_barrier_init(&barrier, NULL, THREAD_NUM);
// 创建线程
for (long i = 0; i < THREAD_NUM; ++i) {
threads_id[i] = i;
pthread_create(&threads[i], NULL, task, &threads_id[i]);
}
// 等待线程结束
for (int i = 0; i < THREAD_NUM; ++i) {
pthread_join(threads[i], NULL);
}
// 销毁屏障
pthread_barrier_destroy(&barrier);
return 0;
}
机制 | 适用场景 | 优点 | 缺点 |
---|---|---|---|
互斥锁 | 简单临界区保护 | 简单高效 | 可能死锁 |
读写锁 | 读多写少场景 | 提高读并发性能 | 实现复杂 |
条件变量 | 线程间状态通知 | 避免忙等待 | 必须配合互斥锁使用 |
信号量 | 资源数量控制/进程间同步 | 灵活控制并发量 | 操作较复杂 |
屏障 | 并行计算同步 | 确保阶段同步 | 不适用于动态线程数 |