基本线程的动作

继续之前C语言线程的文章:文章1 文章2 来了解基本的线程操作。

设置线程属性

设置脱离状态

下面代码中关键的地方在于:

  • 通过 res = pthread_attr_init(&thread_attr); 初始化一个线程属性
  • 通过 res = pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED); 将属性设置为脱离状态(PTHREAD_CREATE_DETACHED),即不能通过调用 pthread_join 来获得另一个线程的退出状态
  • 另外还有一个常用的默认状态是 PTHREAD_CREATE_JOINABLE ,可以允许两个线程重新合并。
  • 属性用完后对其进行清理回收 (void)pthread_attr_destroy(&thread_attr);
  • 通过共享的变量 thread_finished 来检测子线程是否已经结束

代码如下:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h> void *thread_function(void *arg); char message[] = "Hello World";
int thread_finished = 0; int main() {
int res;
pthread_t a_thread; pthread_attr_t thread_attr; res = pthread_attr_init(&thread_attr);
if (res != 0) {
perror("Attribute creation 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);
}
(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);
}

设置调度属性

线程库提供以下调度策略:

| SCHED_FIFO  | 先进先出 (FIFO) 调度。每个线程都有一个固定的优先级;当多个线程具有相同的优先级时,它们按照先进先出 (FIFO) 的顺序运行直到完成 |
| SCHED_RR | 循环 (RR) 调度。每个线程都有固定的优先级;当多个线程具有相同的优先级时,它们按照先进先出 (FIFO) 的顺序在一个 固定的时间片内运行。 |
| SCHED_OTHER | 缺省的 AIX® 调度。每个线程都有一个由调度程序根据线程的活动动态修改的初始优先级;线程的执行是按时间分割的。在其他系统上,这个调度策略可能会不同。 |

设置调度属性和设置很相似:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h> void *thread_function(void *arg); char message[] = "Hello World";
int thread_finished = 0; int main() {
int res;
pthread_t a_thread;
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);
}

取消线程

  • 通过 int pthread_cancel(pthread_t thread); 来请求一个线程终止
  • 通过 int pthread_setcancelstate(int state, int *oldstate) 来设置接受的进程是允许取消请求还是忽略它
  • 通过 int pthread_setcanceltype(int type, int *oldtype) 来设置取消类型, PTHREAD_CANCEL_ASYCHRONOUS 代表接收到取消请求后立即行动, THREAD_CANCEL_DEFERRED 表示在接收到请求后,等待函数执行下述动作之一后才取消线程: pthread_join, pthread_cond_wait, pthread_cond_timeout, pthread_test_cancel, sem_wait, sigwait

代码如下:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h> 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("Caceling 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;
res = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
if (res != 0) {
perror("Thread pthread_setcalcelstate 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 <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h> #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);
}

运行结果如下:

thread_function is running. Argument was 0
Bye from 0
thread_function is running. Argument was 1
thread_function is running. Argument was 2
Bye from 1
thread_function is running. Argument was 3
thread_function is running. Argument was 4
thread_function is running. Argument was 5
Waiting for threads to finish...
Bye from 5
Picked up a thread
Bye from 3
Bye from 2
Bye from 4
Picked up a thread
Picked up a thread
Picked up a thread
Picked up a thread
Picked up a thread
All done

了解更多

参考资料

PS

不得不承认,我失败了。曾计划每天分享一篇python相关知识点但没有做到。失败的原因想找可以找很多比如最近在做一个小的项目、这几天出去聚会没有时间、工作出现问题加班到比较晚等等,然而总结起来不外乎在心里它的重要程度是怎么样的。我反思了下几乎做到一天一篇的这一个月过程做出改变,不再要求一天一篇,而是当我有好的素材要分享时才分享,这样与我与大家都是一件好事,我可以动态调度自己的精力和注意力,比如最近实现了一半的一个odoo项目依赖关系分析器可以尽快把它做完,对于读者来说也可以减少干扰看到更好的分享而不是像我之前有几篇那样划水的。但每周应该会有3-4篇Python的知识可以分享。另外我目前的工作是基于Odoo的,我计划尝试做一些基础的教程来分享这个我熟悉的框架,如果有进展一定会告知感兴趣的读者。感谢读者。

最后向漩涡鸣人致敬,朝他的“说到做到,这就是我的忍道”努力。

理解线程3 c语言示例线程基本操作的更多相关文章

  1. 加深对AQS原理的理解示例二:自己设计一个同步工具,同一时刻最多只有两个线程能访问,超过线程将被阻塞

    /** *@Desc 设计一个同步工具,同一时刻最多只有两个线程能访问,超过线程将被阻塞<br> * 思路分析: * 1.共享锁 两个线程及以内能成功获取到锁 * 2. *@Author ...

  2. 深入理解Java类加载器(二):线程上下文类加载器

    摘要: 博文<深入理解Java类加载器(一):Java类加载原理解析>提到的类加载器的双亲委派模型并不是一个强制性的约束模型,而是Java设计者推荐给开发者的类加载器的实现方式.在Java ...

  3. 深入理解java虚拟机-第13章-线程安全与锁优化

    第十三章 线程安全与锁优化 线程安全 java语言中的线程安全 1 不可变.Immutable 的对象一定是线程安全的 2 绝对线程安全 一个类要达到不管运行时环境如何,调用者都不需要额外的同步措施, ...

  4. android线程 Handler Message Queue AsyncTask线程模型 线程交互 + 修改Button样式 示例 最终easy整合版

     首先原谅我把文章的标题写的这么长.其实我还嫌弃它短了因为 写不下去了所以我就不写了.因为我实在不知道该怎么定义这篇文章的标题或许应该叫 "乱谈"比较合适. 这样可能还体现了 ...

  5. 深入理解JVM - Java内存模型与线程 - 第十二章

    Java内存模型 主内存与工作内存 Java内存模型主要目标:定义程序中各个变量的访问规则,即在虚拟机中将变量存储到内存和从内存中取出变量这样的底层细节.此处的变量(Variable)与Java编程中 ...

  6. 深入理解JVM(③)再谈线程安全

    前言 我们在编写程序的时候,一般是有个顺序的,就是先实现再优化,并不是所有的牛P程序都是一次就写出来的,肯定都是不断的优化完善来持续实现的.因此我们在考虑实现高并发程序的时候,要先保证并发的正确性,然 ...

  7. 理解微信小程序的双线程模型

    有过微信小程序开发经验的朋友应该都知道"双线程模型"这个概念,本文简单梳理一下双线程模型的一些科普知识,学识浅薄,若有错误欢迎指正. 我以前就职于「小程序·云开发」团队,在对外的一 ...

  8. 深入理解java虚拟机(7)---线程安全 & 锁优化

    关于线程安全的话题,足可以使用一本书来讲解这些东西.<Java Concurrency in Practice> 就是讲解这些的,在这里 主要还是分析JVM中关于线程安全这块的内容. 1. ...

  9. go语言实现线程池

    话说真的好久没有写博客了,最近赶新项目,工作太忙了.这一周任务比较少,又可以随便敲敲了. 逛论坛的时候突发奇想,想用go语言实现一个线程池,主要功能是:添加total个任务到线程池中,线程池开启num ...

随机推荐

  1. python 不同目录间的模块调用

    有时候调用的模块不再同一个目录.直接import 是加载不进来的.默认的加载路径是sys.path中指定的路径.如果要指定加载的目录得需要把这个目录加到sys.path里面. 比如要加载父目录的同级目 ...

  2. SQL varchar转float实现数字比较

    select * from table where cast('经纬度' as float ) < 90

  3. IDEA中git的配置与使用

    IDEA中git的配置与使用 1.介绍 git是目前非常流行的版本管理管理软件,因其具有分布式特点,越来越受到企业的欢迎.IDEA作为一款优秀的开发软件,其内部也提供了对git的支持. 2.下载并安装 ...

  4. Vim插件推荐

    看下文时要知道我的<leader>键就是\. ctags C程序阅读辅助工具.在看C/C++代码的时候经常需要在文件之间跳来跳去,这是很麻烦的事,ctags就是解决这种问题的.ctags是 ...

  5. 复制windows CMD命令行中的内容

    标记文本后,按"回车",或鼠标"右键"为从CMD中复制文本. 在CMD中,按鼠标"右键",为在CMD中粘贴文本.

  6. 轻量级HTTP服务器Nginx(Nginx性能优化技巧)

    轻量级HTTP服务器Nginx(Nginx性能优化技巧)   文章来源于南非蚂蚁   一.编译安装过程优化 1.减小Nginx编译后的文件大小在编译Nginx时,默认以debug模式进行,而在debu ...

  7. Java nio socket与as3 socket(粘包解码)连接的应用实例

    对Java nio socket与as3 socket连接的简单应用 <ignore_js_op>Java nio socket与as3 socket连接的应用实例.rar (9.61 K ...

  8. json 序列化和反序列化的3个方法

    https://www.cnblogs.com/caofangsheng/p/5687994.html

  9. Hive 配置显示表头和数据库信息

    在 conf/hive-site.xml 中添加如下配置 <property> <name>hive.cli.print.header</name> <val ...

  10. <strong>和 <b> 的区别

    前几天,看到这样的一个笑话:甲:“我精通前端开发”,乙:“strong和b的区别是什么?” 甲:.... 其实我也搞不清有什么区别,因此我整理了一下: 一.为什么会有这样一个问题 我们在一个没有附加式 ...