资讯专栏INFORMATION COLUMN

理解线程3 c语言示例线程基本操作

A Loity / 646人阅读

摘要:基本线程的动作继续之前语言线程的文章文章文章来了解基本的线程操作。属性用完后对其进行清理回收通过共享的变量来检测子线程是否已经结束代码如下设置调度属性线程库提供以下调度策略先进先出调度。

基本线程的动作

继续之前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 
#include 
#include 
#include 

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...
");
    sleep(1);
  }
  printf("Other thread finished, bye!
");
  exit(EXIT_SUCCESS);
}

void *thread_function(void *arg){
  printf("thread_function is running. Argument was %s
", (char *)arg);
  sleep(4);
  printf("Second thread setting finished flag, and exiting now
");
  thread_finished = 1;
  pthread_exit(NULL);
}
设置调度属性

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

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

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

#include 
#include 
#include 
#include 

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...
");
        sleep(1);
    }
    printf("Other thread finished, bye!
");
    exit(EXIT_SUCCESS);
}

void *thread_function(void *arg) {
    printf("thread_function is running. Argument was %s
", (char *)arg);
    sleep(4);
    printf("Second thread setting finished flag, and exiting now
");
    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 
#include 
#include 
#include 

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...
");
  res = pthread_cancel(a_thread);
  if (res != 0){
    perror("Thread cancelation failed");
    exit(EXIT_FAILURE);
  }
  printf("Waiting for thread to finish...
");
  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
");
  for(i=0; i<10; i++) {
    printf("Thread is still running (%d)...
", i);
    sleep(1);
  }
  pthread_exit(0);
}
主线程创建多个线程示例

代码如下:

#include 
#include 
#include 
#include 

#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...
");
    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
");
        }
        else {
            perror("pthread_join failed");
        }
    }
    printf("All done
");
    exit(EXIT_SUCCESS);
}

void *thread_function(void *arg) {
    int my_number = *(int *)arg;
    int rand_num;

    printf("thread_function is running. Argument was %d
", my_number);
    rand_num=1+(int)(9.0*rand()/(RAND_MAX+1.0));
    sleep(rand_num);
    printf("Bye from %d
", 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
了解更多

Posix多线程编程—线程属性

参考资料

《Linux 程序设计》

http://www.ibm.com/support/kn...

PS

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

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

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/38241.html

相关文章

  • 理解线程1 C语言示例的程序

    摘要:一个简单的语言实现的线程示例在看时,为了更好的理解线程的概念,书中列举了这样一个小例子将程序编译链接后运行,可以看到下面这样的结果这里使用创建新线程,的定义如下根据要求,只有一个指向的指针作为参数,返回的也是指向的指针。 一个简单的C语言实现的线程示例 在看《Beginning Linux Programming》时,为了更好的理解线程的概念,书中列举了这样一个小例子: #inclu...

    lncwwn 评论0 收藏0
  • [Java并发-2]Java如何解决可见性问题的

    摘要:诞生之处就支持多线程,所以自然有解决这些问题的办法,而且在编程语言领域处于领先地位。,线程规则这条是关于线程启动的。在语言里面,的语义本质上是一种可见性,意味着事件对事件来说是可见的,无论事件和事件是否发生在同一个线程里。 之前我们说了:1,可见性2,原子性3,有序性3个并发BUG的之源,这三个也是编程领域的共性问题。Java诞生之处就支持多线程,所以自然有解决这些问题的办法,而且在编...

    lk20150415 评论0 收藏0
  • JS高级入门教程

    摘要:解析首先简称是由欧洲计算机制造商协会制定的标准化脚本程序设计语言。级在年月份成为的提议,由核心与两个模块组成。通过引入统一方式载入和保存文档和文档验证方法对进行进一步扩展。其中表示的标记位正好是低三位都是。但提案被拒绝了。 JS高级入门教程 目录 本文章定位及介绍 JavaScript与ECMAScript的关系 DOM的本质及DOM级介绍 JS代码特性 基本类型与引用类型 JS的垃...

    zsy888 评论0 收藏0
  • 双重检查锁定与延迟初始化

    摘要:基于的双重检查锁定的解决方案对于前面的基于双重检查锁定来实现延迟初始化的方案指示例代码,我们只需要做一点小的修改把声明为型,就可以实现线程安全的延迟初始化。 双重检查锁定的由来 在java程序中,有时候可能需要推迟一些高开销的对象初始化操作,并且只有在使用这些对象时才进行初始化。此时程序员可能会采用延迟初始化。但要正确实现线程安全的延迟初始化需要一些技巧,否则很容易出现问题。比如,下...

    yvonne 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<