基本线程的动作

继续之前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. Android 编码风格规范,很赞哦

    1. 前言 这份文档参考了 Google Java 编程风格规范和 Google 官方 Android 编码风格规范.该文档仅供参考,只要形成一个统一的风格,见量知其意就可. 1.1 术语说明 在本文 ...

  2. 【Microsoft Azure学习之旅】测试消息队列(Service Bus Queue)是否会丢消息

    组里最近遇到一个问题,微软的Azure Service Bus Queue是否可靠?是否会出现丢失消息的情况? 具体缘由如下, 由于开发的产品是SaaS产品,为防止消息丢失,跨Module消息传递使用 ...

  3. May 05th 2017 Week 18th Friday

    No matter what have happened today, the sun will just rise in the morning of tomorrow. 无论今天发生了什么,明天早 ...

  4. C++ POD类型

    POD( Plain Old Data)概念: Arithmetic types (3.9.1), enumeration types, pointer types, and pointer to m ...

  5. leetcode:查找

    1.  word ladder 题目: Given two words (start and end), and a dictionary, find the length of shortest t ...

  6. C# windows 计划任务 程序编写

    编写windows 计划任务只需要在普通的类里面使用main方法就好了,因为任务计划在创建后走的是程序的主方法,代码如下: using System; using System.Collections ...

  7. 谷歌浏览器模拟手机浏览器且指定IP运行

    1.背景 因为现在项目是要做分布式,而以前使用谷歌浏览器模拟手机运行做的分布式,是指定在某台机器运行是通过Jenkins配置,来指定服务器,但是这样有一个问题,如果大家都同时配置到某台电脑,那台服务器 ...

  8. 模拟停车POJ(3505)

    题目链接:http://poj.org/problem?id=3505 解题报告: #include <stdio.h> #include <iostream> #includ ...

  9. 基于ngx_lua模块的waf开发实践

    0x00 常见WAF简单分析 WAF主要分为硬件WAF和软件防火墙,硬件WAF如绿盟的NSFOCUS Web Application Firewall,软件防火墙比较有名的是ModSecurity,再 ...

  10. python title() upper() lower() 以首字母大写的方式显示每个单词/将字符串改为全部大写或全部小写

    以首字母大写的方式显示每个单词 [root@chenbj python]# cat name.py #!/usr/bin/env python # _*_ coding:utf-8 _*_ name ...