线程休眠/组赛
在线程不满足执行条件时,我们一般希望线程能休眠或者阻塞等待条件满足时再执行;或者,当我们创建新线程时,一般会让新线程阻塞一段时间,防止新线程生命周期过短,返回错误的值。
本文简单介绍了线程休眠的两种方式:
sleep/usleep
的方式休眠;pthread_cond_wait()/pthread_cond_timedwaid()
;
sleep/usleep
使用 sleep()/usleep()
会让线程进入休眠,sleep
的单位时
s
s
s,usleep
的单位是
u
s
us
us。很多人并不建议在多线程中使用 sleep()/usleep()
进行休眠操作。说是会休眠整个进程,但是我在测试中,并没有遇到休眠整个进程的问题。
以下用一个实例来说明如何使用 sleep/usleep
休眠线程。
以下代码中建立了两个线程:thread1
每隔
5
s
5s
5s 打印一次数据,thread2
每隔
1
s
1s
1s 遇到偶数打印一次数据。
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/time.h>
void *thread1(void *param)
{
int i;
for(i = 0; i < 100; i++) {
sleep(5); // 休眠 5 s
if(i == 50) pthread_exit(NULL);
printf("%s: %d: thread1: %d\n", __FILE__, __LINE__, i);
}
}
void *thread2(void *param)
{
int i;
for(i = 0; i < 100; i++) {
usleep(1000000); // 休眠 1s
printf("%s: %d: thread2: %d\n", __FILE__, __LINE__, i);
}
}
int main()
{
pthread_t pd1, pd2;
int error;
// 创建线程
error = pthread_create(&pd1, NULL, thread1, NULL);
if(error) {
printf("%s: %d: 创建线程 thread1 失败: %d\n", __FILE__, __LINE__, error);
return -1;
}
error = pthread_create(&pd2, NULL, thread2, NULL);
if(error) {
printf("%s: %d: 创建线程 thread2 失败: %d\n", __FILE__, __LINE__, error);
return -1;
}
// 释放线程资源
pthread_join(pd1, NULL);
pthread_join(pd2, NULL);
return 0;
}
结果:
pthread.c: 30: thread2: 0
pthread.c: 30: thread2: 1
pthread.c: 30: thread2: 2
pthread.c: 30: thread2: 3
pthread.c: 18: thread1: 0
pthread.c: 30: thread2: 4
pthread.c: 30: thread2: 5
pthread.c: 30: thread2: 6
pthread.c: 30: thread2: 7
# `pthread_cond_wait/pthread_cond_timedwait` ---- 大家都非常推荐使用 `pthread_cond_wait/pthread_cond_timedwait`。`pthread_cond_wait/pthread_cond_timedwait`是一系列动作的集合:**解锁**、**等待条件为true**、**加锁**。所以使用上述两个函数时要加锁。 - `pthread_cond_wait`:不机时条件等待; - `pthread_cond_timedwait`:计时条件等待;
通过 pthread_cond_wait/pthread_cond_timedwait
改写上述例子。
pthread1
每个 10 10 10s 打印一次,或者被信号触发才打印一次;pthread2
每个 1 1 1s 遇到偶数打印一次,每 2 s 2s 2s 触发一次条件。
#pragma GCC diagnostic error "-std=c++11"
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/time.h>
static pthread_cond_t cond; // 条件
static pthread_mutex_t mutex; // 锁
void *thread1(void *)
{
int i;
struct timeval now;
struct timespec outtime;
for(i = 0; i < 100; i++) {
// 暂停10s
gettimeofday(&now, NULL);
outtime.tv_sec = now.tv_sec + 10;
outtime.tv_nsec = now.tv_usec*1000;
pthread_mutex_lock(&mutex); // 加锁
pthread_cond_timedwait(&cond, &mutex, &outtime); // 动作集合:解锁、等待条件为 true、加锁
//pthread_cond_wait(&cond, &mutex);
pthread_mutex_unlock(&mutex); // 解锁
if(i == 50) pthread_exit(NULL);
printf("%s: %d: thread1: %d\n", __FILE__, __LINE__, i);
}
}
void *thread2(void *)
{
int i;
for(i = 0; i < 100; i++) {
usleep(1000000); // 暂停1s
printf("%s: %d: thread2: %d\n", __FILE__, __LINE__, i);
// 偶数时触发cond信号
if (i % 2 == 0) {
pthread_mutex_lock(&mutex); // 加锁
pthread_cond_signal(&cond); // 触发条件
//pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mutex); // 解锁
}
}
}
int main()
{
pthread_t pd1, pd2;
int error;
// 初始化变量
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond, NULL);
// 创建线程
error = pthread_create(&pd1, NULL, thread1, NULL);
if(error) {
printf("%s: %d: 创建线程 thread1 失败: %d\n", __FILE__, __LINE__, error);
return -1;
}
error = pthread_create(&pd2, NULL, thread2, NULL);
if(error) {
printf("%s: %d: 创建线程 thread2 失败: %d\n", __FILE__, __LINE__, error);
return -1;
}
// 等待线程结束并回收线程资源
pthread_join(pd1, NULL);
pthread_join(pd2, NULL);
return 0;
}
结果:
test.cpp: 42: thread2: 0
test.cpp: 30: thread1: 0
test.cpp: 42: thread2: 1
test.cpp: 42: thread2: 2
test.cpp: 30: thread1: 1
test.cpp: 42: thread2: 3
test.cpp: 42: thread2: 4
test.cpp: 30: thread1: 2
test.cpp: 42: thread2: 5
test.cpp: 42: thread2: 6
test.cpp: 30: thread1: 3
test.cpp: 42: thread2: 7
test.cpp: 42: thread2: 8
test.cpp: 30: thread1: 4
test.cpp: 42: thread2: 9
test.cpp: 42: thread2: 10
test.cpp: 30: thread1: 5
test.cpp: 42: thread2: 11