1.   所谓线程就是“一个进程内部的一个控制序列”。也就是一个进程内部的并行的基础!

2.    Linux进程可以看成只有一个控制线程:
      一个进程在同一时刻只做一件事情。有了多个控制线程以后,
      在程序设计时可以把进程设计成在同一时刻能够做不止一件事,
      每个线程处理各只独立的任务。即所谓并行!
     
3.     线程的优点:
          (1)通过为每种事件类型的处理分配单独的线程,能够简化处理异步时间的代码。
          (2)多个线程可以自动共享相同的存储地址空间和文件描述符。
          (3)有些问题可以通过将其分解从而改善整个程序的吞吐量。
          (4)交互的程序可以通过使用多线程实现相应时间的改善,多线程可以把程序中
               处理用户输入输出的部分与其它部分分开。

4.       线程的缺点:
         线程也有不足之处。编写多线程程序需要更全面更深入的思考。
         在一个多线程程序里,因时间分配上的细微偏差或者因共享了不该共享的
         变量而造成不良影响的可能性是很大的。调试一个多线程程序也
         比调试一个单线程程序困难得多。     
     
5.    线程标识:
      我们已经知道进程有进程ID就是pid_t,那么线程也是有自己的ID的pthread_t数据类型!
      注意:实现的时候可以用一个结构来代表pthread_t数据类型,所以可以移植的操作系统
            不能把它作为整数处理。因此必须使用函数来对来对两个线程ID进行比较。
     
6.    pthread_cancel:取消同一进程中的其他线程(注意是取消其他线程)
     
       intpthread_cancel(pthread_t tid);
      若成功返回0,否则返回错误编号。
      注意:pthread_cancel并不等待线程终止,它仅仅提出请求。是否真的执行还看目标线程的
            state和type的设置了!
     
7.  pthread_cleanup_push 和pthread_cleanup_pop:线程清理处理程序     
     
       voidpthread_cleanup_push( void ( * rtn ) ( void * ),void *arg );
       voidpthread_cleanup_pop( int exe );
       参数:
            rtn:  处理程序入口地址
             arg:传递给处理函数的参数
      线程可以安排它退出时需要调用的函数,这样的函数称为线程清理处理程序,线程可以建立多个清理处理程序。
      注意:此处是使用栈保存的,所以是先进后处理原则!
            如果线程是通过从启动例程中返回而终止的,它的处理程序就不会调用。
     
      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
      ATTENTION:
                  pthread_cleanup_push注册一个回调函数,如果你的线程在对应的pthread_cleanup_pop
                  之前异常退出(return是正常退出,其他是异常),那么系统就会执行这个回调函数(回调函
                  数要做什么你自己决定)。但是如果在pthread_cleanup_pop之前没有异常退出,
                  pthread_cleanup_pop就把对应的回调函数取消了,
     
       所以请注意:
            只有在“清理函数”的设置和取消之间有异常的退出,才会调用我们设置的“清理函数”。
            否则是不会输出的!
            一般的触发条件是:在之间有pthread_exit(非正常退出);或者有取消点时候!
           
       关于“取消点” (cancellation point ):
            例如执行下面代码:
                            printf("sleep\n");
                            sleep(10);
                             printf("wake \n");
      在sleep函数中,线程睡眠,结果收到cancel信号,这时候线程从sleep中醒来,但是线程不会立刻退出。
      >>>>>:     
            函数:pthread_testcancel():
            描述:函数在运行的线程中创建一个取消点,如果cancellation无效则此函数不起作用。
            
            pthread的建议是:如果一个函数是阻塞的,那么你必须在这个函数前后建立 “ 取消点 ”, 比如:
                            printf("sleep\n");
                           pthread_testcancel();
                            sleep(10);
                            pthread_testcancel();
                             printf("wake \n");
            在执行到pthread_testcancel的位置时,线程才可能响应cancel退出进程
           
            对于一些函数来说本身就是有cancellation point 的,那么可以不管,但是大部分还是没有的,
            所以要使用pthread_testcancel来设置一个取消点,那么也并不是对于所有的函数都是有效的,
            对于有延时的函数才是有效的,更清楚的说是有时间让pthread_cancel响应才是OK的!
           
       附加:
            POSIX中的函数cancellation点的:
            pthread_join
            pthread_cond_wait
            thread_cond_timewait
            pthread_testcancel
            sem_wait
            sigwait       都是cancellation点.
            下面的这些系统函数也是cancellation点:
             accept
             fcntl
             open
             read
             write
             lseek
             close
             send
            sendmsg
             sendto
            connect
             recv
            recvfrom
            recvmsg
             system
            tcdrain
             fsync
             msync
             pause
             wait
            waitpid
            nanosleep
 
            其它的一些函数如果调用了上面的函数, 那么, 它们也是cancellation点.
             intpthread_setcancelstate (int STATE, int *OLDSTATE);
            用于允许或禁止处理cancellation,
            STATE可以是:PTHREAD_CANCEL_ENABLE, PTHREAD_CANCEL_DISABLE

intpthread_setcanceltype (int TYPE, int *OLDTYPE);
            设置如何处理cancellation, 异步的还是推迟的.
            TYPE可以是:PTHREAD_CANCEL_ASYNCHRONOUS, PTHREAD_CANCEL_DEFERRED
              
      >>>>        
      摘录:http://blogt.chinaunix.net/space.php?uid=23381466&do=blog&id=58787

什么是取消点(cancelation point)?

资料中说,根据POSIX标准,pthread_join()、pthread_testcancel()、pthread_cond_wait()、
            pthread_cond_timedwait()、sem_wait()、sigwait()等函数以及read()、write()等会引起阻塞
            的系统调用都是Cancelation-point。而其他pthread函数都不会引起 Cancelation动作。但
            是pthread_cancel的手册页声称,由于LinuxThread库与C库结合得不好,因而目前C库函
             数都不是Cancelation-point;但CANCEL信号会使线程从阻塞的系统调用中退出,并置
            EINTR错误码,因此可以在需要作为Cancelation-point的系统调用前后调用pthread_testcancel(),
            从而达到POSIX标准所要求的目标,即如下代码段:

pthread_testcancel();
             retcode =read(fd, buffer, length);
            pthread_testcancel();

我发现,对于C库函数来说,几乎可以使线程挂起的函数都会响应CANCEL信号,终止线程,
            包括sleep、delay等延时函数。                    
    本篇文章来源于 Linux公社网站(www.linuxidc.com)  原文链接:http://www.linuxidc.com/Linux/2012-03/57249p2.htm

8、示例代码:

/*
* ThreadCancel.c
*
* Created on: Aug 17, 2013
* Author: root
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <pthread.h>
#include <errno.h> #define NUM_THREADS 5
void* search(void *);
void print_it(void*); pthread_t threads[NUM_THREADS];
pthread_mutex_t lock;
int tries;
int started;
int main(){
int i, pid;
pid = getpid();
printf("Search for the number=%d...\n", pid);
pthread_mutex_init(&lock,NULL);
for(started=;started<NUM_THREADS; started++){
pthread_create(&threads[started], NULL, search, (void*)pid);
}
for(i=; i<NUM_THREADS; i++){
pthread_join(threads[i], NULL);
}
printf("It took %d tries to find the number.\n", tries);
return ;
} void print_it(void * arg){
int *try = (int *)arg;
pthread_t tid;
tid = pthread_self();
printf("Thread %lx was canceled on its %d try.\n", tid, *try);
} void * search(void * arg){
int num = (int)arg;
int i,j,ntries;
pthread_t tid;
tid = pthread_self();
while(pthread_mutex_trylock(&lock) == EBUSY){
pthread_testcancel(); //thread may be canceled and call cancel function handler !
}
printf("current thread tid:%lx.\n", tid);
srand((int)tid);
printf("current thread tid:%lx, after srand method.\n", tid);
i = rand() & 0xFFFFFF;
pthread_mutex_unlock(&lock);
ntries = ;
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
while(started < NUM_THREADS){
sched_yield();
}
pthread_cleanup_push(print_it, (void*)&ntries);
while(){
i = (i+) & 0xffffff;
ntries++;
if(num == i){
while(pthread_mutex_trylock(&lock) == EBUSY){
printf("Thread %lx found the number! But not get lock!\n", tid);
pthread_testcancel();
}
tries = ntries;
printf("Thread %lx found the number!\n", tid);
for(j=;j<NUM_THREADS;j++){
if(threads[j] != tid){
pthread_cancel(threads[j]);
}
}
break;
} if(ntries % ==){
pthread_testcancel();
}
} pthread_cleanup_pop();
return ((void*));
}

因为是多线程运行,所以运行结果可能有好几个,运行结果(一):

运行结果(二):

(转)Linux 多线程编程---pthread_testcancel()等讲解的更多相关文章

  1. Linux多线程编程小结

     Linux多线程编程小结 前一段时间由于开题的事情一直耽搁了我搞Linux的进度,搞的我之前学的东西都遗忘了,非常烦躁的说,如今抽个时间把之前所学的做个小节.文章内容主要总结于<Linux程序 ...

  2. Linux多线程编程阅读链接

    1. 进程与线程的一个简单解释(阮一峰) 2. linux 多线程编程 3. Linux 的多线程编程的高效开发经验 (IBM)

  3. Linux多线程编程和Linux 2.6下的NPTL

    Linux多线程编程和Linux 2.6下的NPTL 在Linux 上,从内核角度而言,基本没有什么线程和进程的区别--大家都是进程.一个进程的多个线程只是多个特殊的进程他们虽然有各自的进程描述结构, ...

  4. Linux多线程编程初探

    Linux线程介绍 进程与线程 典型的UNIX/Linux进程可以看成只有一个控制线程:一个进程在同一时刻只做一件事情.有了多个控制线程后,在程序设计时可以把进程设计成在同一时刻做不止一件事,每个线程 ...

  5. ZT 为什么pthread_cond_t要和pthread_mutex_t同时使用 || pthread/Linux多线程编程

    为什么线程同步的时候pthread_cond_t要和pthread_mutex_t同时使用 (2009-10-27 11:07:23) 转载▼ 标签: 杂谈 分类: 计算机 举一个例子(http:// ...

  6. 【操作系统作业-lab4】 linux 多线程编程和调度器

    linux多线程编程 参考:https://blog.csdn.net/weibo1230123/article/details/81410241 https://blog.csdn.net/skyr ...

  7. Linux多线程编程实例解析

    Linux系统下的多线程遵循POSIX线程接口,称为 pthread.编写Linux下的多线程程序,需要使用头文件pthread.h,连接时需要使用库libpthread.a.顺便说一下,Linux ...

  8. Linux多线程编程之详细分析

    线程?为什么有了进程还需要线程呢,他们有什么区别?使用线程有什么优势呢?还有多线程编程的一些细节问题,如线程之间怎样同步.互斥,这些东西将在本文中介绍.我见到这样一道面试题: 是否熟悉POSIX多线程 ...

  9. Linux多线程编程(不限Linux)【转】

    ——本文一个例子展开,介绍Linux下面线程的操作.多线程的同步和互斥. 前言 线程?为什么有了进程还需要线程呢,他们有什么区别?使用线程有什么优势呢?还有多线程编程的一些细节问题,如线程之间怎样同步 ...

随机推荐

  1. Sqli labs系列-less-5&6 报错注入法(下)

    我先输入 ' 让其出错. 然后知道语句是单引号闭合. 然后直接 and 1=1 测试. 返回正常,再 and 1=2 . 返回错误,开始猜表段数. 恩,3位.让其报错,然后注入... 擦,不错出,再加 ...

  2. JS基础入门篇(二十七)—BOM

    虽然上次写到js基础篇(二十四),这次直接写到(二十七).是为了提醒自己中间有几篇没写.特此说明一下啊. 1.window.open() 使用a标签呢,点击一下a标签页面才会跳转,有时候我们需要做的操 ...

  3. Linux监控cpu,内存,磁盘脚本

    #!/bin/bash # CPU_us=$(vmstat | awk '{print $13}' | sed -n '$p') CPU_sy=$(vmstat | awk '{print $14}' ...

  4. python正常时间和unix时间戳相互转换的方法

    python正常时间和unix时间戳相互转换的方法 本文实例讲述了python正常时间和unix时间戳相互转换的方法.分享给大家供大家参考.具体分析如下: 这段代码可以用来转换常规时间格式为unix时 ...

  5. 21. Blog接口开发

    一般的系统由登录.增删改查所组成.我们的Blog同样如此.我们会开发登录.创建博客.删除博客.修改博客.查询博客等功能.话不多说,我们直接展开实践吧. 思路分析 创建项目.既然我们要创建一个blog, ...

  6. upc组队赛5 Bulbs

    Bulbs 题目描述 Greg has an m × n grid of Sweet Lightbulbs of Pure Coolness he would like to turn on. Ini ...

  7. LINUX 安装PHP GD库遇到的坑

    本文借鉴:https://www.cnblogs.com/gaohj/p/3152646.html linux下为php添加GD库的步骤如下: 一.下载 gd-.tar.gz http://www.b ...

  8. Java对象引用四个级别(强、软、弱、虚)

    最近,高级Java技术栈微信群中,有一些猿友在讨论JVM中对象的周期问题,有谈到引用的级别,现在为大家做个总结吧,虽然大多数公司并没有意识或者用到这些引用,但了解这些基本概念对熟悉整个垃圾回收机制和面 ...

  9. 【题解】Ride to Office

    题目描述 起点与终点相隔4500米.现Charley 需要从起点骑车到终点.但是,他有个习惯,沿途需要有人陪伴,即以相同的速度, 与另外一个人一起骑.而当他遇到以更快的速度骑车的人时,他会以相应的速度 ...

  10. void v.s. void *

    在學校老師一定都會教void是無型態的返回值例如 void swap(int *a, int *b){      int temp = *a;      *a = *b;      *b = temp ...