线程学习第一课--线程同步

在一个程序中的多个执行路线叫做线程
线程是一个进程内部的一个控制序列

当进程执行fork调用时,创建出该进程的一份新的拷贝,这个新的进程拥有自己的变量和pid
时间调度是独立的,执行也几乎是独立的。

当进程创建一个新的线程的时候,新的执行线程将有自己的栈,但是和创建者共享局部变量,
文件描述符,信号句柄和当前目录状态。

线程的优点:
    有时候让程序同时做两件事情是很有用的;对于数据服务器来说,这个明显的多任务工作如果用多进程
    的方式来完成将很难做到高效率,因为各个不同的进程必须紧密合作才能满足加锁和数据一致性方面的
    要求,而用多线程来完成就比多进程要容易的多。
    
    一个混杂这输入,计算和输出的程序,可以将这几个部分分离为三个线程来执行,从而改善程序的执行
    的性能。
    
    一般的线程之间的切换需要操作系统做的工作比进程之间切换少得多,因此多个线程对资源的需求要远
    小于多个进程
    
线程的缺点是:
    线程的设计可以非常的复杂,是一个立刻让自己自讨苦吃的方式。
    
    多线程的调试比单线程的调试要困难的多,因为线程之间的交互非常难以控制。
    
    将大量的计算分成两个部分,并把两个部分作为两个不同的线程来运行在一台单处理器上不一定获得更快
    的运行效率,因为中的cpu速度是一定的。

第一个简单的线程程序:创建新的线程,并等待新的线程结束

首先因为一个全局变量可能被多个线程共享造成全局变量的不够用或者不精确,为了解决这个问题,我们需要
可重入的例程,可重入的代码可以被多次调用而仍然正常工作。代码的可重入部分通常使用局部变量,这使得每次
对该代码的调用都将获得它自己的唯一的一份数据拷贝。

宏_REENTRANT来告诉编译器我们需要可重入功能。
它主要完成下面的三件事情:
    对部分函数重新定义它们的可安全重入的版本,这些函数的名字一般不会改变只是函数名后面添加-r字符串。
    
    stdio.h中原来以宏的形式实现的一些函数将变成可安全重入的函数。
    
    在errno.h中定义的变量errno现在将变成一个函数调用,它能够以一种安全的多线程方式来获取真正的errno值。
    
pthread_create函数的作用是创建一个新线程,类似于创建新进程的fork函数

1 #include <pthread.h>
2 int pthread_create(pthread_t * thread, pthread_attr_t * attr, void * (*start_routine)(void *), void *arg);
3                   ____________________   ___________   _______________________________________   _______

第一个参数是指向pthread_t类型的指针,线程被创建时候,这个指针指向的变量中被写入一个
                  标识符,我们可以用这个标识符来引用新的线程。
                  
                  第二个参数是设置线程的属性,一般不要特殊的属性的时候就设置为NULL
                  
                  第三个参数是线程将要启动执行的函数,我们需要传入一个函数地址,该函数以一个指向void
                  的指针为参数,返回值也是一个指向void的指针,因此传递任一类型的参数并返回一个任一类型
                  的指针。fork调用后父子进程将在同一位置继续执行下去,但是新创建的线程必须明确提供给
                  它一个函数指针,新线程将在这个新位置开始执行。
                  
                  第四个参数是传递给这个函数的参数    
函数成功时返回0失败时返回错误代码

pthread_exit函数可以使线程终止执行

1 #include <pthread.h>
2 void pthread_exit(void * retval);

函数终止调用它的线程并返回一个指向某个对象的指针

pthread_join函数在线程中等价于用在进程中收集子进程信息的wait函数

1 #include <pthread.h>
2 int pthread_join(pthread_t th, void ** thread_return);

第一个参数指定了要等待的线程,线程通过pthread_create返回的标识符来指定
第二个参数是一个指针,它指向了另外一个指针,而否则指向{线程的返回值}
成功的时候返回0失败的时候返回错误代码

简单的线程程序例子:

 1 #include <stdio.h>
 2 #include <unistd.h>
 3 #include <stdlib.h>
 4 #include <pthread.h>
 5
 6 void *thread_function(void *arg);//定义了函数原形
 7
 8 char message[] = "Hello World";//定义了全局变量字符串数组
 9
10 int main()
11 {
12     int res;
13     pthread_t a_thread;
14     void *thread_result;
15     res = pthread_create(&a_thread, NULL, thread_function, (void *)message);
16     //创建新的线程,传递一个pthread_t结构的地址,设置默认,执行函数,和函数参数是最后两个
17     if (res != 0)
18     {
19         perror("Thread creation failed");
20         exit(EXIT_FAILURE);
21     }
22     printf("Waiting for thread to finish...\n");//创建成功,打印一句话,现在有两个线程
23     res = pthread_join(a_thread, &thread_result);//等待新创建的线程的结束,得到指向线程返回值的指针
24     if (res != 0) {
25         perror("Thread join failed");
26         exit(EXIT_FAILURE);
27     }
28     printf("Thread joined, it returned %s\n", (char *)thread_result);//新线程执行完毕,打印返回值
29     printf("Message is now %s\n", message);//重新打印新的全局变量
30     exit(EXIT_SUCCESS);
31 }
32
33 void *thread_function(void *arg)
34 {
35     printf("thread_function is running. Argument was %s\n", (char *)arg);//新线程执行打印全局变量
36     sleep(3);//延时
37     strcpy(message, "Bye!");//全局变量赋值为新
38     pthread_exit("Thank you for the CPU time");//线程的返回值
39 }

程序的执行的结果:

1 [email protected]:~/c_program/544977-blp3e/chapter12$ gcc thread1.c -o thread1 -lpthread
2 [email protected]:~/c_program/544977-blp3e/chapter12$ ./thread1
3 Waiting for thread to finish...
4 thread_function is running. Argument was Hello World
5 Thread joined, it returned Thank you for the CPU time
6 Message is now Bye!

新线程修改了字符串数组,旧的线程可以访问这个修改,要是fork出的子进程就不能实现这些。

第二个简单的线程程序:两个线程同时执行

 1 #include <stdio.h>
 2 #include <unistd.h>
 3 #include <stdlib.h>
 4 #include <pthread.h>
 5
 6 void *thread_function(void *arg);//定义新线程执行函数的原形
 7 int run_now = 1;//定义一个全局变量
 8 char message[] = "Hello World";//定义一个全局字符串数组
 9
10 int main()
11 {
12     int res;
13     pthread_t a_thread;
14     void *thread_result;
15     int print_count1 = 0;
16
17     res = pthread_create(&a_thread, NULL, thread_function, (void *)message);//创建新的线程
18     if (res != 0)
19     {//失败处理
20         perror("Thread creation failed");
21         exit(EXIT_FAILURE);
22     }
23
24     while(print_count1++ < 20) {//先执行1的打印,然后改变全局b被设置为2回到while继续循环,睡1秒
25         if (run_now == 1) {
26             printf("1");
27             run_now = 2;
28         }
29         else {
30             sleep(1);
31         }
32     }
33
34     printf("\nWaiting for thread to finish...\n");
35     res = pthread_join(a_thread, &thread_result);//等待新创建的线程的结束,打印返回值
36     if (res != 0) {
37         perror("Thread join failed");
38         exit(EXIT_FAILURE);
39     }
40     printf("Thread joined\n");
41     exit(EXIT_SUCCESS);
42 }
43
44 void *thread_function(void *arg)
45 {//新线程来执行这个函数,传递的函数是字符串数组指针
46     int print_count2 = 0;//局部变量
47
48     while(print_count2++ < 20)
49     {
50         if (run_now == 2) //新进程会在这里面执行打印2并把全局变量设置为1,继续while然后睡1秒
51         {
52             printf("2");
53             run_now = 1;
54         }
55         else {
56             sleep(1);
57         }
58     }//最后一次打印2
59
60     sleep(3);//睡3秒之后新线程退出
61 }

程序的执行效果:

1 [email protected]:~/c_program/544977-blp3e/chapter12$ gcc thread2.c -o thread2 -lpthread
2 [email protected]:~/c_program/544977-blp3e/chapter12$ ./thread2
3 1212121212121212121//不知道为什么最后的一个2没有输出,或者有时候在Thread joined之前输出
4 Waiting for thread to finish...
5 Thread joined
6 //总的来说每个线程通过设置run_now变量的方法来通知另一个线程开始运行,然后等待另一个线程
7 //改变变量后再次运行,这个例子显示了两个线程之间自动的交替执行。

线程同步

上面的两个线程同步是通过轮询技术,所以效率很低。
有一组设计好的函数为我们提供了更好的控制线程执行和访问代码临界区域的方法

两种基本的方法:
    信号量:作用如同看守一段代码的看门人
    互斥量:作用如同保护代码的一个互斥设备

这两个方法看起来是相似的,事实上,它们可以相互通过对方来实现。

但是对于一些情况,可能使用信号量或互斥量中的一个更符合问题的语义,并且效果更好。
例如:
    想控制任一时刻只能有一个线程可以访问的一些内存,使用互斥量就要自然的多。
    想控制对一组相同对象的访问时,更合适使用计数信号量。

用信号量进行同步:
    信号量一般常用来保护一段代码
    使其每次只能被一个执行线程运行,要完成这个工作,要使用二进制信号量。
    使其每次只能被有限数目的线程运行,就要使用计数信号量。

信号量函数的名字以sem_开头

#include <semaphore.h>
int sem_init(sem_t * sem, int pshared, unsigned int value);//完成信号量的创建
/*初始化由sem指向的信号量对象,设置它的共享选项,并设置一个初始的整数值
                0表示信号量是当前进程的局部信号量
                否则就可以在多个进程之间共享*/
#include <semaphore.h>
int sem_wait(sem_t * sem);//以原子操作的方式给信号量的值减1
int sem_post(sem_t * sem);//以原子操作的方式给信号量的值加1
/*这两个函数参数是个指针,指针指向的对象是sem_init初始化的信号量
对于值为0的信号量调用sem_wait,这个函数会等待,直到有其他的信号量的值使其不再是0为止。*/
#include <semaphore.h>
int sem_destory(sem_t * sem)//用完信号量之后对它进行清理
/*要是清理的信号量正在被一些线程等待,就会收到一个错误。*/

上面函数,和大多数的函数一样成功的时候返回0

线程信号量的实例:

 1 #include <stdio.h>
 2 #include <unistd.h>
 3 #include <stdlib.h>
 4 #include <pthread.h>
 5 #include <semaphore.h>//包含这个头文件使得我们可以使用信号量
 6
 7 void *thread_function(void *arg);//定义线程执行的函数
 8 sem_t bin_sem;
 9
10 #define WORK_SIZE 1024//宏定义一个数值
11 char work_area[WORK_SIZE];//分配一个空的字符数组
12
13 int main()
14 {
15     int res;
16     pthread_t a_thread;
17     void *thread_result;
18
19     res = sem_init(&bin_sem, 0, 0);//创建一个初始值是0的局部信号量
20     if (res != 0)
21     {//错误处理
22         perror("Semaphore initialization failed");
23         exit(EXIT_FAILURE);
24     }
25     res = pthread_create(&a_thread, NULL, thread_function, NULL);//创建一个新的线程
26     if (res != 0)
27     {//错误处理
28         perror("Thread creation failed");
29         exit(EXIT_FAILURE);
30     }
31     printf("Input some text. Enter ‘end‘ to finish\n");//创建成功先打印这句话,下面执行函数
32     while(strncmp("end", work_area, 3) != 0)
33     {//区域为空字符串不相等,函数返回不等于0成立,执行循环体
34         fgets(work_area, WORK_SIZE, stdin);//老线程从标准输入读取这么多大小的输入放到指定的地方
35         sem_post(&bin_sem);//给信号量加1,相当于释放信号量
36     }
37     printf("\nWaiting for thread to finish...\n");
38     res = pthread_join(a_thread, &thread_result);//等待子进程的结束
39     if (res != 0)
40     {
41         perror("Thread join failed");
42         exit(EXIT_FAILURE);
43     }
44     printf("Thread joined\n");
45     sem_destroy(&bin_sem);
46     exit(EXIT_SUCCESS);
47 }
48
49 void *thread_function(void *arg)
50 {
51     sem_wait(&bin_sem);//给信号量减一
52     while(strncmp("end", work_area, 3) != 0)//前三个字符一样的话就返回0,如果输入正确,现在是一样
53     {
54         printf("You input %d characters\n", strlen(work_area) -1);//要是出入多的话,新线程统计输入。
55         sem_wait(&bin_sem);
56  //然后信号量减1但是不成功只好等待,老线程会加1,之后唤醒,执行比较,决定循环还是退出
57     }
58     pthread_exit(NULL);//新线程退出
59 }

程序的执行的效果:

 1 [email protected]:~/c_program/544977-blp3e/chapter12$ ./thread3
 2 Input some text. Enter ‘end‘ to finish
 3 hi end
 4 You input 6 characters
 5 helloend
 6 You input 8 characters
 7 h
 8 You input 1 characters
 9 nihao
10 You input 6 characters
11 end
12
13 Waiting for thread to finish...
14 Thread joined

对上面的程序进行部分的修改:

 1 #include <stdio.h>
 2 #include <unistd.h>
 3 #include <stdlib.h>
 4 #include <pthread.h>
 5 #include <semaphore.h>
 6
 7 void *thread_function(void *arg);
 8 sem_t bin_sem;
 9
10 #define WORK_SIZE 1024
11 char work_area[WORK_SIZE];
12
13 int main() {
14     int res;
15     pthread_t a_thread;
16     void *thread_result;
17
18     res = sem_init(&bin_sem, 0, 0);
19     if (res != 0) {
20         perror("Semaphore initialization failed");
21         exit(EXIT_FAILURE);
22     }
23     res = pthread_create(&a_thread, NULL, thread_function, NULL);
24     if (res != 0) {
25         perror("Thread creation failed");
26         exit(EXIT_FAILURE);
27     }
28
29     printf("Input some text. Enter ‘end‘ to finish\n");
30     while(strncmp("end", work_area, 3) != 0) {//输入不是end执行循环体
31       if (strncmp(work_area, "FAST", 4) == 0) {//输入前四个字符是FAST的时候执行
32         sem_post(&bin_sem);//信号量加1释放,
33         strcpy(work_area, "Wheeee...");//拷贝这个字符串给全局字符串,这会导致新线程没时间统计FAST的长度
34       } else {
35         fgets(work_area, WORK_SIZE, stdin);
36       }
37       sem_post(&bin_sem);//这里信号量又加1释放
38     }//新线程等待时候主线程比较,执行while,不执行if获取输入但是信号量加1,这时新线程执行第三次统计
39
40     printf("\nWaiting for thread to finish...\n");
41     res = pthread_join(a_thread, &thread_result);
42     if (res != 0) {
43         perror("Thread join failed");
44         exit(EXIT_FAILURE);
45     }
46     printf("Thread joined\n");
47     sem_destroy(&bin_sem);
48     exit(EXIT_SUCCESS);
49 }
50
51 void *thread_function(void *arg) {
52     sem_wait(&bin_sem);//新线程获得信号量减一
53     while(strncmp("end", work_area, 3) != 0) {//字符串现在不等执行循环体
54         printf("You input %d characters\n", strlen(work_area) -1);//统计输入字符串
55         sem_wait(&bin_sem);//减1之后还不是是1判断while再执行统计,然后等待去减1
56     }
57     pthread_exit(NULL);
58 }

执行的效果:

 1 [email protected]:~/c_program/544977-blp3e/chapter12$ ./thread3a
 2 Input some text. Enter ‘end‘ to finish
 3 hi
 4 You input 2 characters
 5 FASTTT
 6 You input 8 characters
 7 You input 8 characters
 8 You input 8 characters
 9 endend
10
11 Waiting for thread to finish...
12 Thread joined
13 [email protected]:~/c_program/544977-blp3e/chapter12$ 

为了解决上面的问题 可以再增加一个信号量,让主线程等到统计线程完成字符个数的统计后再继续执行

用互斥量进行同步:

允许程序员锁住某个对象,使得每次只能有一个线程访问它
为了控制对关键代码的访问,必须在进入这段代码之前锁住一个互斥量,然后在完成之后解锁它

1 #include <pthread.h>
2 int pthread_mutex_init(pthread_mutex_t * mutex, const pthread_mutexattr_t * mutexattr);
3 int pthread_mutex_lock(pthread_mutex_t * mutex);
4 int pthread_mutex_unlock(pthread_mutex_t * mutex);
5 int pthread_mutex_destory(pthread_mutex_t * mutex);

成功时返回0失败时返回错误代码不会设置errno所以必须对函数的返回代码进行检查
/*init函数的第二个参数允许我们设置互斥量的属性,默认的属性是fast
但是是有缺点的如果程序试图对一个已经加了锁的互斥量调用了lock函数,程序会被阻塞
而拥有互斥量的这个线程正是现在被阻塞车线程,多以互斥量就永远不会被锁了。程序死锁。
这个问题可以改变互斥量的属性来解决,我们可以让它检查这种情况并返回一个错误
或者让它递归的操作,给同一个线程加上多个锁,但是注意在后面执行同等数量的解锁操作。*/

线程互斥量程序:

 1 #include <stdio.h>
 2 #include <unistd.h>
 3 #include <stdlib.h>
 4 #include <pthread.h>
 5 #include <semaphore.h>
 6
 7 void *thread_function(void *arg);//定义新线程执行函数
 8 pthread_mutex_t work_mutex; //定义一个这个类型的互斥量
 9
10 #define WORK_SIZE 1024//定义一个数
11 char work_area[WORK_SIZE];//分配一个内存
12 int time_to_exit = 0;//初始化一个整型为0
13
14 int main() {
15     int res;
16     pthread_t a_thread;
17     void *thread_result;
18     res = pthread_mutex_init(&work_mutex, NULL);//创建一个互斥量到这个参数的地址
19     if (res != 0) {//出错处理
20         perror("Mutex initialization failed");
21         exit(EXIT_FAILURE);
22     }
23     res = pthread_create(&a_thread, NULL, thread_function, NULL);//创建一个新线程指向这个函数
24     if (res != 0) {//出错处理
25         perror("Thread creation failed");
26         exit(EXIT_FAILURE);
27     }
28
29     pthread_mutex_lock(&work_mutex);//锁定创建出的互斥量
30     printf("Input some text. Enter ‘end‘ to finish\n");//打印一句话
31     while(!time_to_exit) {//因为非0为真执行循环                //老线程接手继续执行
32         fgets(work_area, WORK_SIZE, stdin);//标准输入一些东西,(加锁读入数据)
33         pthread_mutex_unlock(&work_mutex);//解锁互斥量(解锁统计数据)
34         while(1) {//恒执行周期性执行
35             pthread_mutex_lock(&work_mutex);//尝试锁定互斥量成功的话检查时候要计数
36             if (work_area[0] != ‘\0‘) {//输入不为空执行这个循环
37                 pthread_mutex_unlock(&work_mutex);//解锁互斥量
38                 sleep(1);//睡觉让新线程去执行统计            //不为空解锁交给新线程
39             }
40             else {//输入为空的话就跳出循环此时互斥量还是被锁定的        //为空锁定退出
41                 break;
42             }
43         }
44     }
45     pthread_mutex_unlock(&work_mutex);    //再接着为空的话对锁定退出执行这个解锁
46     printf("\nWaiting for thread to finish...\n");
47     res = pthread_join(a_thread, &thread_result);//等待子进程结束
48     if (res != 0) {
49         perror("Thread join failed");
50         exit(EXIT_FAILURE);
51     }
52     printf("Thread joined\n");
53     pthread_mutex_destroy(&work_mutex);    //销毁互斥量
54     exit(EXIT_SUCCESS);
55 }
56
57 void *thread_function(void *arg) {
58     sleep(1);//先睡1秒,保证老线程先执行
59     pthread_mutex_lock(&work_mutex);//新线程试图锁定这个互斥量,要是已经被锁定就阻塞
60     while(strncmp("end", work_area, 3) != 0) {//不退出也就是不等于end时候执行计数
61         printf("You input %d characters\n", strlen(work_area) -1);
62         work_area[0] = ‘\0‘;//给区域赋值为\0
63         pthread_mutex_unlock(&work_mutex);//解锁互斥量
64         sleep(1);//去睡觉让老线程执行
65         pthread_mutex_lock(&work_mutex);            //新线程锁定互斥量
66         while (work_area[0] == ‘\0‘ ) {            //为空传过来
67             pthread_mutex_unlock(&work_mutex);        //首先解锁,
68             sleep(1);                        //然后睡觉
69             pthread_mutex_lock(&work_mutex);            //从等待中执行完成回来锁定
70         }
71     }
72     time_to_exit = 1;                //要是程序请求退出设置这个为1
73     work_area[0] = ‘\0‘;
74     pthread_mutex_unlock(&work_mutex);    //解锁
75     pthread_exit(0);                //退出
76 }

程序执行效果:

 1 [email protected]:~/c_program/544977-blp3e/chapter12$ ./thread4
 2 Input some text. Enter ‘end‘ to finish
 3 123
 4 You input 3 characters
 5
 6 You input 0 characters
 7
 8 You input 0 characters
 9 endend
10
11 Waiting for thread to finish...
12 Thread joined

参考文献:Linux程序设计

date:2015年 06月 30日 星期二 13:04:58 CST

时间: 2024-10-01 21:43:08

线程学习第一课--线程同步的相关文章

Magento学习第一课——目录结构介绍

Magento学习第一课--目录结构介绍 一.Magento为何强大 Magento是在Zend框架基础上建立起来的,这点保证了代码的安全性及稳定性.选择Zend的原因有很多,但是最基本的是因为zend框架提供了面向对象的代码库并且有很好的团队支持.通过这个框架,Magento主要围绕三个基本点建立: 1. 灵活性:我们相信每一个解决方案都像它的商务支持一样是独一无二的.Magento的代码可以无缝定制的. 2. 可升级性:Magento可方便的实行定制且不丧失升级的能力,因为从社区中获得核心代

IOS学习第一课

第一课,也就是公认的HelloWorld了. 步骤如下: 1  创建helloWorld工程 2 实现QuizViewController.h文件 3 实现QuizViewController.m文件 4 使用StorBoard绘制界面 5 连接输出口 6 定义事件 IOS学习第一课

微信SDK开发学习第一课

1.为什么学习微信API开发? 微信注册用户6亿,把微信当做推广平台已经成为主流. 2.微信SDK主要功能有哪些? 主要功能:分享给朋友,分享到朋友圈 3.如何使用微信SDK? 3.1 打开微信SDK主页注册账号:https://open.weixin.qq.com/ 3.2 点击管理中心-->移动应用-->创建移动应用:填写基本信息 移动应用名称:微信SDK学习第一课 英文名称(选填):WebChat SDK interface to learn one. 移动应用简介:学习微信开发第一课

jquery 学习第一课之start

1.$选取符 ( $ == jQuery ) (1) $("div").addClass("special");选取本页面中的所有<div>元素,然后将这些div加上都加上一个名为“special”的CSS样式. (2)$("div")选取所有的div元素. (3)$(“#body”)选取id为body的元素. (4)$("div #body")选取id为body的<div>. (5)$("d

FPGA入门学习第一课:二分频器

分频器还是比较简单的,一般的思路是:每数几个时钟就输出一个时钟.最简单的当数二分频器了,每当时钟上升沿(或下降沿)就把输出翻转一下.这样就刚好实现了二分频器了. 网上也搜到了最简实现”二分频最简单了,一句话就可以了:               always @ (negedge clk)        clk_2<=~clk_2;“ 但仿真时却发现无法输出 分析是因为输出信号的初始状态不确定造成的,于是加了一句初始化,就可以正常分频了 但观察他们生成的逻辑结构图是一样的 完整代码如下: mod

linux学习第一课

linux学习第一课,打卡打卡 原文地址:https://blog.51cto.com/12910091/2436322

线程学习四:线程池

Java通过Executors提供四种线程池,分别为: newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程. newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待. newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行. newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,

python学习第一课要点记录

写在要点之前的一段话,留给将来的自己:第一次参加编程的培训班,很兴奋很激动,之前都是自己在网上找免费的视频来看,然后跟着写一些课程中的代码,都是照着模子写,没有自己过多的思考.感觉这样学不好,除了多写以外,还得自己思考,经过了自己思考的源码,才能真正成为自己的东西.在上课前,班主任就让我们自己想一下,通过这个培训,要达到的目标.其实我的目标很简单,不求通过这个培训班能成为什么开发工程师,年薪百万,达到人生巅峰,赢取白富美.那个不现实,我只求能够在现在实际工作中(我的工作主要是网络运维,还兼有系统

线程学习第二课--脱离线程,调度线程,取消线程,多线程

例如主线程继续为用户提供服务的同时创建第二个线程这个线程的作用是将用户正在编辑的数据进行备份存储那么备份结束之后第二个线程就可以字节终止没必要再回到主线程中区 称这样的线程为脱离线程,可以通过修改属性或者调用pthread_detach的方法来创建这里我们从属性的角度研究脱离线程 1 #include <pthread.h> 2 int pthread_atte_init(pthread_attr_t * attr); 函数的作用是初始化一个线程属性对象 对应的回收函数是pthread_att