标签(空格分隔): Linux程序设计
线程是一个进程内部的一个控制序列。
当在进程中创建一个新线程时,新的执行线程将拥有自己的栈(因此也有自己的局部变量),但与它的创建者共享全局变量、文件描述符、信号处理函数和当前目录状态。
线程的优点:
#include<pthread.h>
//创建线程
int pthread_create(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);
//thread: 指向pthread_t类型的指针,用来引用该新线程;
//attr: 用于设置线程的属性,一般为NULL;
//第3,4个参数为线程将要启动执行的函数,以及传递给该函数的参数
//返回:调用成功返回0,失败则返回错误代码
//线程等待函数
int pthread_join(pthread_t th, void **thread_return);
//th: 指定将要等待的线程
//thread_return: 指向线程返回值的指针(的指针)。
//返回:成功返回0,失败则返回错误代码
//线程终止函数
void pthread_exit(void *retval);
//retval: 指向线程返回值的指针(pthread_join可以获取该指针)
示例:
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<pthread.h>
void *thread_function(void *arg);
char msg[] = "Hello World";
int main()
{
int res;
pthread_t a_thread;
void *thread_result;
res = pthread_create(&a_thread, NULL, thread_function, (void *)msg);
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", msg);
exit(EXIT_SUCCESS);
}
void *thread_function(void *arg)
{
printf("Thread function is runing. Argument was %s\n",(char *)arg);
sleep(3);
strcpy(msg,"Bye!");
pthread_exit("Thank you for the CPU time.");
}
参考:https://docs.oracle.com/cd/E19253-01/819-7051/sync-12/index.html
#include<pthread.h>
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr);
//mutex: 事先声明过的pthread_mutex_t对象的指针
//mutexattr: 设置互斥量的属性,默认为fast。该参数一般置为NULL
//返回: 成功返回0,失败则返回错误代码
//加锁
int pthread_mutex_lock(pthread_mutex_t *mutex);
//解锁
int pthread_mutex_unlock(pthread_mutex_t *mutex);
//销毁
int pthread_mutex_destroy(pthread_mutex_t *mutex);
示例:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
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);
}
参考:
IBM Knowledge Center: 使用条件变量
知乎:条件变量之稀里糊涂的锁
有了互斥锁,为什么还要条件变量?
linux多线程使用pthread_cond条件变量
条件变量(cond)是在多线程程序中用来实现"等待->唤醒"逻辑常用的方法。条件变量利用线程间共享的全局变量进行同步的一种机制。
条件变量必须始终与互斥对象一起使用。主要为了防止竞争死锁(防止pthread_cond_signal在pthread_cond_wait之前调用,导致线程永久等待)。
保护条件的互斥对象必须在等待条件前被锁定。线程可等待通过调用 pthread_cond_wait 或者 pthread_cond_timedwait 子例程发信号的条件。子例程以不可分割的方式解锁互斥对象并阻塞调用线程,直到条件收到信号。当调用返回时,互斥对象再次被锁定。
pthread_cond_wait 子例程无限期阻塞线程。如果条件永不收到信号,那么线程将永不唤醒。因为 pthread_cond_wait 子例程提供取消点,所以如果启用可取消,那么退出此死锁的唯一方法是取消被阻塞的线程。
pthread_cond_wait函数的返回并不意味着条件的值一定发生了变化,必须重新检查条件的值。
pthread_cond_signal 子例程至少唤醒一个当前在指定条件上被阻塞的线程。根据调度策略选择被唤醒的线程。
pthread_cond_broadcast 子例程唤醒当前被阻塞在指定的条件下的每一个线程。但是,线程能够在调用子例程返回后即开始等待相同的条件。
#include <pthread.h>
//定义条件变量
pthread_cond_t cond;
//初始化条件变量
int pthread_cond_init (pthread_cond_t *cond, const pthread_condattr_t *attr)
//cond:事先定义好的条件变量指针
//attr:事先定义好的条件变量属性(默认NULL)
//等待
1)调用时:解除锁,等待条件变量,然后阻塞
2)返回时:收到信号,再次锁定
int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex);
//cond:初始化后的条件变量
//mutex:绑定的互斥量
//定时等待
int pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *timeout);
//发送信号
int pthread_cond_signal (pthread_cond_t *condition);
//销毁条件变量
int pthread_cond_destroy (pthread_cond_t *cond)
示例:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
#include<stdbool.h>
void *thread_function1(void *arg);
void *thread_function2(void *arg);
pthread_mutex_t count_mutex;
pthread_cond_t count_threshold_cv;
bool ready = false;
char msg1[] = "this is thread 1";
char msg2[] = "this is thread 2";
int main()
{
pthread_t thread1;
pthread_t thread2;
pthread_mutex_init(&count_mutex, NULL);
pthread_cond_init (&count_threshold_cv, NULL);
pthread_create(&thread1, NULL, thread_function1, (void *)msg1);
pthread_create(&thread2, NULL, thread_function2, (void *)msg2);
printf("waiting for thread to finish...\n");
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
pthread_mutex_destroy(&count_mutex);
pthread_cond_destroy(&count_threshold_cv);
return 0;
}
void *thread_function1(void *arg)
{
printf("Tips:%s\n", (char *)arg);
pthread_mutex_lock(&count_mutex);
while (false == ready)
{
pthread_cond_wait(&count_threshold_cv, &count_mutex);
printf("thread1 in pthread_cond_wait\n");
}
if(true == ready)
printf("now ready = true in thread1.\n");
pthread_mutex_unlock(&count_mutex);
pthread_exit(0);
}
void *thread_function2(void *arg)
{
sleep(3);
printf("Tips:%s\n", (char *)arg);
pthread_mutex_lock(&count_mutex);
ready = true;
printf("thread2 set ready = true\n");
pthread_mutex_unlock(&count_mutex);
pthread_cond_signal(&count_threshold_cv);
pthread_exit(0);
}
判断条件状态的时候ready==false放在了while循环中,而不是if中,这是因为pthread_cond_wait()阻塞在条件变量上的时候,即使其他的线程没有就该条件变量发出通知(pthread_cond_signal()/pthread_cond_broadcast()),条件变量也有可能会自己醒来(pthread_cond_wait()函数返回),因此需要重新检查一下共享变量上的条件成不成立,确保条件变量是真的收到了通知,否则继续阻塞等待。关于虚假唤醒的相关介绍,可以戳这里查看维基百科下面的几个引用:https://en.wikipedia.org/wiki/Spurious_wakeup。
原文:https://www.cnblogs.com/wuxubj/p/10805386.html