1.什么是线程?
让一个进程同时做两件事情或者多件事情,看起来是非常有用的,但用fork调用创建新进程的代价太高,在这种情况下,线程就能发挥作用,他能实现两件事情或者更多事情以一种非常紧密的方式同时发生。那么什么是线程呢?
在一个程序中的多个执行路线叫做线程,更准确的定义是:线程是一个进程内部的一个控制序列。弄清楚fork系统调用和创建新线程的区别非常重要。
当进程执行fork系统调用时,将创建出该进程的一份新副本。这个新进程拥有自己到底变量和自己的pid,它的时间调度也是独立的,它的执行几乎完全独立于父进程。
当在进程中创建一个新线程时,新的执行线程将拥有自己的栈(有自己的局部变量),但与他的创建者共享全局变量、文件描述符、信号处理函数和当前目录状态。
2.线程的优缺点
先来看一看线程的优缺点。
优点:
1.让程序看起来好像是在同时做两件事是很有用的。(例如:在编辑文档的同时对文档中的单词数进行实时统计。)
2.对于一个有多步操作的程序来说,使之分离为多个线程来执行,能改善程序的执行效率。(例如一个需要同时处理多个网络连接的服务器应用程序,线程可以让他在等待连接的时候同时做一些其他有用的事情)
3.一般而言,线程之间切换需要操作系统做的工作比进程之间的切换少得多,因此多线程的对资源的需求要远小于多个进程。
缺点:
1.编写多线程程序需要非常仔细的设计。
2.对多线程程序的调试要比对单线程的程序的调试困难的多。
3.多线程对于单核cpu来说,不一定更加有效率。
3.一个简单的多线程程序
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
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");
}
为保证编译通过,请采用以下命令:执行程序:
Waiting for thread to finish...
thread_function is running. Argument was Hello World
Thread joined, it returned Thank you for the CPU time
Message is now Bye!
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
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);
}
执行程序:
12121212121212121212
Waiting for thread to finish...
Thread joined
4.线程同步
4.1信号量同步
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <semaphore.h>
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);
}
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);
while(strncmp("end", work_area, 3) != 0) {
printf("You input %d characters\n", strlen(work_area) -1);
sem_wait(&bin_sem);
}
pthread_exit(NULL);
}
执行:Input some text. Enter 'end' to finish
hello world!
You input 12 characters
welcome to china!
You input 17 characters
end
Waiting for thread to finish...
Thread joined
4.2互斥量同步(常用)
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <semaphore.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);
}
[aaa@localhost libFile]$ ./thread4Input some text. Enter 'end' to finish
hello world!
You input 12 characters
i love linux!
You input 13 characters
end
Waiting for thread to finish...
Thread joined