1、定义:
当在进程中创建一个新的线程时,新执行线程将拥有自己栈空间隐刺也有自己的局部变量),但是它与创建者共享全局变量、文件描述符、信号处理函数和当前的目录状态
2、优点:
3、缺点:
4、线程有一套完整的与其有关额函数库,它们中大多数函数名都以pthread_开头,为了使用这些函数库,必须定义宏_REENTRANT,头文件为pthread.h,编译程序额时候用选项-lpthread来链接线程库
例子char message[]主线程和子线程共享的变量
#include
#include
#include
#include
#include
void *thread_function(void *arg);
char message[] = "Hello World";
int main() {
int res;
pthread_t a_thread;
void *thread_result;
res = pthread_create(&a_thread, NULL, thread_function, (void *)message);
if (res != 0) {
perror("Thread creation failed");
exit(EXIT_FAILURE);
}
printf("Waiting for thread to finish...\n");
res = pthread_join(a_thread, &thread_result);
if (res != 0) {
perror("Thread join failed");
exit(EXIT_FAILURE);
}
printf("Thread joined, it returned %s\n", (char *)thread_result);
printf("Message is now %s\n", message);
exit(EXIT_SUCCESS);
}
void *thread_function(void *arg) {
printf("thread_function is running. Argument was %s\n", (char *)arg);
sleep(3);
strcpy(message, "Bye!");
pthread_exit("Thank you for the CPU time");
}
子线程创建后,父子线程是通过CPU在线程快速切换来完成“看起来像是同时执行”的动作,除了线程局部变量外,所有其他的变量都将在一个进程中的所有线程间共享,例子如下:
#include
#include
#include
#include
void *thread_function(void *arg);
int run_now = 1;
char message[] = "Hello World";
int main() {
int res;
pthread_t a_thread;
void *thread_result;
int print_count1 = 0;
res = pthread_create(&a_thread, NULL, thread_function, (void *)message);
if (res != 0) {
perror("Thread creation failed");
exit(EXIT_FAILURE);
}
while(print_count1++ < 20) {
if (run_now == 1) {
printf("1");
run_now = 2;
}
else {
sleep(1);
}
}
printf("\nWaiting for thread to finish...\n");
res = pthread_join(a_thread, &thread_result);
if (res != 0) {
perror("Thread join failed");
exit(EXIT_FAILURE);
}
printf("Thread joined\n");
exit(EXIT_SUCCESS);
}
void *thread_function(void *arg) {
int print_count2 = 0;
while(print_count2++ < 20) {
if (run_now == 2) {
printf("2");
run_now = 1;
}
else {
sleep(1);
}
}
sleep(3);
}
计数信号量同步例子:
#include
#include
#include
#include
#include
#include
void *thread_function(void *arg);
sem_t bin_sem;
#define WORK_SIZE 1024
char work_area[WORK_SIZE];
int main() {
int res;
pthread_t a_thread;
void *thread_result;
res = sem_init(&bin_sem, 0, 0);
if (res != 0) {
perror("Semaphore initialization failed");
exit(EXIT_FAILURE);
}
res = pthread_create(&a_thread, NULL, thread_function, NULL);
if (res != 0) {
perror("Thread creation failed");
exit(EXIT_FAILURE);
}
printf("Input some text. Enter 'end' to finish\n");
while(strncmp("end", work_area, 3) != 0) {
fgets(work_area, WORK_SIZE, stdin);
sem_post(&bin_sem);//信号量+1表示,共享变量可操作
}
/*以下可应对:连续快速的给出两组数据而导致的子线程没有时间处理,信号量的逻辑运算错误问题/*
/*
while(strncmp("end", work_area, 3) != 0) {
if (strncmp(work_area, "FAST", 4) == 0) {
sem_post(&bin_sem);
strcpy(work_area, "Wheeee...");
} else {
fgets(work_area, WORK_SIZE, stdin);
}
*/
sem_post(&bin_sem);
}
printf("\nWaiting for thread to finish...\n");
res = pthread_join(a_thread, &thread_result);
if (res != 0) {
perror("Thread join failed");
exit(EXIT_FAILURE);
}
printf("Thread joined\n");
sem_destroy(&bin_sem);
exit(EXIT_SUCCESS);
}
void *thread_function(void *arg) {
sem_wait(&bin_sem);//线程阻塞,直到信号量不为0
while(strncmp("end", work_area, 3) != 0) {
printf("You input %d characters\n", strlen(work_area) -1);
sem_wait(&bin_sem);//线程阻塞,直到信号量不为0
}
pthread_exit(NULL);
}
补充说明:
以上程序是有缺陷的,应考虑主线程连续快速的给出两组数据而导致的子线程没有时间处理,信号量的逻辑运算错误问题
#include
#include
#include
#include
#include
#include
void *thread_function(void *arg);
pthread_mutex_t work_mutex; /* protects both work_area and time_to_exit */
#define WORK_SIZE 1024
char work_area[WORK_SIZE];
int time_to_exit = 0;
int main() {
int res;
pthread_t a_thread;
void *thread_result;
res = pthread_mutex_init(&work_mutex, NULL);
if (res != 0) {
perror("Mutex initialization failed");
exit(EXIT_FAILURE);
}
res = pthread_create(&a_thread, NULL, thread_function, NULL);
if (res != 0) {
perror("Thread creation failed");
exit(EXIT_FAILURE);
}
pthread_mutex_lock(&work_mutex);
printf("Input some text. Enter 'end' to finish\n");
while(!time_to_exit) {
fgets(work_area, WORK_SIZE, stdin);
pthread_mutex_unlock(&work_mutex);
while(1) {
pthread_mutex_lock(&work_mutex);
if (work_area[0] != '\0') {
pthread_mutex_unlock(&work_mutex);
sleep(1);
}
else {
break;
}
}
}
pthread_mutex_unlock(&work_mutex);
printf("\nWaiting for thread to finish...\n");
res = pthread_join(a_thread, &thread_result);
if (res != 0) {
perror("Thread join failed");
exit(EXIT_FAILURE);
}
printf("Thread joined\n");
pthread_mutex_destroy(&work_mutex);
exit(EXIT_SUCCESS);
}
void *thread_function(void *arg) {
sleep(1);
pthread_mutex_lock(&work_mutex);//新线程试图加锁,如果锁已被锁住,则阻塞直到锁被释放
while(strncmp("end", work_area, 3) != 0) {
printf("You input %d characters\n", strlen(work_area) -1);
work_area[0] = '\0';
pthread_mutex_unlock(&work_mutex);
sleep(1);//解锁后等待主线程运行
pthread_mutex_lock(&work_mutex);//试图加锁,如果锁已被锁住,则阻塞直到锁被释放
while (work_area[0] == '\0' ) {
pthread_mutex_unlock(&work_mutex);
sleep(1);
pthread_mutex_lock(&work_mutex);
}
}
time_to_exit = 1;//有申请退出程序的请求,置标志
work_area[0] = '\0';
pthread_mutex_unlock(&work_mutex);
pthread_exit(0);
}
假设我们在主线程继续为用户提供服务的同时创建了第二个线程,新线程的作用是将用户正在编辑的数据文件进行备份存贮,备份工作技术后,第二个线程就可以直接终止了,它没必要再回到主线程中,此时我们就可以创建脱线线程
->该例子中,子线程是脱线线程,开始后独立结束,并没有返回线程状态给主线程
->调度策略设置后,需要设置调度策略参数,该策略决定谁获取cpu的执行权重比例
#include
#include
#include
#include
void *thread_function(void *arg);
char message[] = "Hello World";
int thread_finished = 0;
int main() {
int res;
pthread_t a_thread;
void *thread_result;
pthread_attr_t thread_attr;
**int max_priority;
int min_priority;
struct sched_param scheduling_value;**
res = pthread_attr_init(&thread_attr);//初始化线程属性对象
if (res != 0) {
perror("Attribute creation failed");
exit(EXIT_FAILURE);
}
res = pthread_attr_setschedpolicy(&thread_attr, SCHED_OTHER);//设置线程调度策略
if (res != 0) {
perror("Setting schedpolicy failed");
exit(EXIT_FAILURE);
}
res = pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);//设置线程脱线属性
if (res != 0) {
perror("Setting detached attribute failed");
exit(EXIT_FAILURE);
}
res = pthread_create(&a_thread, &thread_attr, thread_function, (void *)message);//创建线程
if (res != 0) {
perror("Thread creation failed");
exit(EXIT_FAILURE);
}
max_priority = sched_get_priority_max(SCHED_OTHER);//获取可用的最大优先级级别
min_priority = sched_get_priority_min(SCHED_OTHER);//获取可用的最小优先级级别
scheduling_value.sched_priority = min_priority;
res = pthread_attr_setschedparam(&thread_attr, &scheduling_value);//设置调度参数
if (res != 0) {
perror("Setting schedpolicy failed");
exit(EXIT_FAILURE);
}
(void)pthread_attr_destroy(&thread_attr);//销毁线程属性对象
while(!thread_finished) {
printf("Waiting for thread to say it's finished...\n");
sleep(1);
}
printf("Other thread finished, bye!\n");
exit(EXIT_SUCCESS);
}
void *thread_function(void *arg) {
printf("thread_function is running. Argument was %s\n", (char *)arg);
sleep(4);
printf("Second thread setting finished flag, and exiting now\n");
thread_finished = 1;
pthread_exit(NULL);
}
#include
#include
#include
#include
void *thread_function(void *arg);
int main() {
int res;
pthread_t a_thread;
void *thread_result;
res = pthread_create(&a_thread, NULL, thread_function, NULL);
if (res != 0) {
perror("Thread creation failed");
exit(EXIT_FAILURE);
}
sleep(3);
printf("Canceling thread...\n");
**res = pthread_cancel(a_thread);//主线程内取消子线程**
if (res != 0) {
perror("Thread cancelation failed");
exit(EXIT_FAILURE);
}
printf("Waiting for thread to finish...\n");
res = pthread_join(a_thread, &thread_result);
if (res != 0) {
perror("Thread join failed");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
void *thread_function(void *arg) {
int i, res, j;
**res = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);//设置子线程被取消使**能位
if (res != 0) {
perror("Thread pthread_setcancelstate failed");
exit(EXIT_FAILURE);
}
**res = pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);//设置子线程被取消的时候的动作类型**
if (res != 0) {
perror("Thread pthread_setcanceltype failed");
exit(EXIT_FAILURE);
}
printf("thread_function is running\n");
for(i = 0; i < 10; i++) {
printf("Thread is still running (%d)...\n", i);
sleep(1);
}
pthread_exit(0);
}
#include
#include
#include
#include
#include
#define NUM_THREADS 6
void *thread_function(void *arg);
int main() {
int res;
pthread_t a_thread[NUM_THREADS];
void *thread_result;
int lots_of_threads;
for(lots_of_threads = 0; lots_of_threads < NUM_THREADS; lots_of_threads++) {
res = pthread_create(&(a_thread[lots_of_threads]), NULL, thread_function, (void *)lots_of_threads);
if (res != 0) {
perror("Thread creation failed");
exit(EXIT_FAILURE);
}
/* sleep(1); */
}
printf("Waiting for threads to finish...\n");
for(lots_of_threads = NUM_THREADS - 1; lots_of_threads >= 0; lots_of_threads--) {
res = pthread_join(a_thread[lots_of_threads], &thread_result);
if (res == 0) {
printf("Picked up a thread\n");
} else {
perror("pthread_join failed");
}
}
printf("All done\n");
exit(EXIT_SUCCESS);
}
void *thread_function(void *arg) {
int my_number = (int)arg;
int rand_num;
printf("thread_function is running. Argument was %d\n", my_number);
rand_num=1+(int)(9.0*rand()/(RAND_MAX+1.0));
sleep(rand_num);
printf("Bye from %d\n", my_number);
pthread_exit(NULL);
}