线程创建与等待




一.概述:

首先谈一下为什么要有线程。众所周知,一个进程只能进行一个执行流,虽然能创建子进程,但创建,终止,切换进程和进程间的通信的开销比较大,所以现代操作系统一般都使用线程。

现在再谈一下我所了解的线程功能。一般可以这样认为,进程负责的是分配资源,而线程负责的是调度和执行。线程又叫轻量级进程。而传统的进程即负责分配资源,又承担一个线程的执行。

进程和线程的区别:除了上面功能与性能的不同,还可以从进程管理的角度来区别。在单线程模型中,进程的表示包括它的进程控制块,用户地址空间,以及进程执行中管理调用/返回行为的用户栈,内核栈。在多线程环境中,进程只有一个与之关联的进程控制块和用户地址空间,而线程都有一个独立的栈,还有独立的控制块(包括寄存器,优先级和其它与线程相关的状态信息)。如下图:(摘自操作系统精髓与设计原理第4章)

注:如果在多处理器机器上,多线程的性能会更优。




二.相关函数:(PS:这里的线程库函数是由POSIX标准定义的,称为POSIX thread或者pthread。)

  1. pthread_create:     int  pthread_create(pthread_t *pthread, const pthread_attr_t *attr,

    void *(*start_toutine)(void *),  void *arg)

函数功能:创建一个线程,使线程从传入的函数指针所指的函数中开始执行。

pthread参数:输出型参数,创建成功会把线程id放入里面。

attr参数:用来设置线程的属性,如线程的分离状态属性,线程栈的大小等。一般为NULL就可以了。

start_toutine参数:函数指针,用于指明线程从哪里开始执行。

arg参数:传入函数指针所指的函数的参数。

返回值:所有pthread函数都是成功返回0,失败返回一个错误号。可以用strerror显示错误号。

PS:主线程会从函数返回出继续往下执行。

2.pthread_exit:void pthread_exit(void *retval)

函数功能:线程可以调用自己进行注销操作。

retval参数:退出时返回的值。

3.pthread_cancel:int  pthread_cancel(pthread_t  pthread)

函数功能:注销线程id为pthread的线程。

返回值:成功返回0,失败返回一个错误号。

4.pthread_join:int  pthread_join(pthread_t pthread, void** retval)

函数功能:将线程id为pthread的线程挂起等待,直到线程终止,终止状态保持到retval中。

retval参数:输出型参数,用于保存线程终止的终止状态。不同的终止方法有不同的终止状态:

(1).如果线程通过return返回,retval中指向的单元里存放的是线程函数的返回值。

(2).如果线程被别的线程调用pthread_cancel异常终止,retval指向的单元中存放的是常数PTHREAD_CALCELED。

(3).如果线程自己调用pthread_exit()函数终止的,retval指向的单元中存放的是传给pthead_exit()的参数。

返回值:成功返回0,失败返回一个错误号。




三.相关代码:(PS:编译时要加    -Lpthread)

  1. 创建一个进程:
1 #include<stdio.h>                                                                                                                                              
  2 #include<stdlib.h>
  3 #include<pthread.h>
  4 
  5 pthread_t tid;
  6 
  7 void* create_thread(void *ptr)
  8 {
  9     printf("%s . pid is:%d  tid is:%ul \n",(char *)ptr, (int)getpid(), (unsigned long long)pthread_self());
 10     return NULL;
 11 }
 12 
 13 int main()
 14 {
 15     int err = pthread_create(&tid, NULL, create_thread, "i‘m a thread");
 16     if(err != 0)
 17     {
 18         printf("create thread failed! info is :%s", strerror(err));
 19         exit(err);
 20     }
 21 
 22     printf("main thread run. pid is:%d  tid is:%ul \n", (int)getpid(), (unsigned long long)pthread_self());//linux 下tid为一个地址值
 23     sleep(1);
 24     return 0;
 25 }

执行结果:

2.线程等待:

 1 #include<stdio.h>                                                                                                                                              
  2 #include<stdlib.h>
  3 #include<pthread.h>
  4 
  5 void *create_thread1(void *ptr)
  6 {
  7     printf("this is thread1\n");
  8     return (void *)1;
  9 }
 10 
 11 void *create_thread2(void *ptr)
 12 {
 13     printf("this is thread2\n");
 14     pthread_exit((void *)2);
 15 }
 16 
 17 void *create_thread3(void *ptr)
 18 {
 19     while(1)
 20     {
 21         printf("this is thread3,waiting for be calceled.....\n");
 22         sleep(1);
 23     }
 24     return NULL;
 25 }
 26 
 27 int main()
 28 {
 29     pthread_t tid;
 30     void* ret;
 31 
 32     int err1 = pthread_create(&tid, NULL, create_thread1, NULL);
 33     if(err1 != 0)
 34     {
 35         printf("create thread failed!");
 36     }
 37     pthread_join(tid, &ret);
 38     printf("thread is returned,tid is:%ul return code is:%d \n", (unsigned long long)pthread_self(), (int)ret);
 39 
 40     int err2 = pthread_create(&tid, NULL, create_thread2, NULL);
 41     if(err2 != 0)
 42     {
 43         printf("create thread failed!");
 44     }
 45     pthread_join(tid, &ret);
 46     printf("thread is exited,tid is:%ul return code is:%d \n", (unsigned long long)pthread_self(), (int)ret);
 47 
 48     int err3 = pthread_create(&tid, NULL, create_thread3, NULL);
 49     if(err3 != 0)
 50     {
 51         printf("create thread failed!");
 52     }
 53     sleep(3);
 54     pthread_cancel(tid);
 55     pthread_join(tid, &ret);
 56     printf("thread is canceled,tid is:%ul return code is:%d \n", (unsigned long long)pthread_self(), (int)ret);
 57 
 58     return 0;
 59 }

执行结果:

时间: 2024-10-23 23:01:49

线程创建与等待的相关文章

win32多线程 (一) 线程创建与结束等待

#include "stdafx.h"#include <Windows.h>#include <iostream> using namespace std; DWORD WINAPI ThreadFuncFirst(LPVOID param){ int iCount = 50; while(iCount--){  cout<<"\nThreadFuncFirst:"<<iCount; } return 0;} DWO

线程创建代码

#include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <string.h> #include <sys/syscall.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #ifndef T_DESC #define T_DESC(x, y) (y) #end

Windows核心编程之创建可等待定时器及其APC回调

概述 创建可等待定时器是Windows内部线程同步的方式之一,本文简单讲述如何使用这一内核对象进行线程同步. 使用方法 创建对象: //创建事件内核对象,默认未触发状态 HANDLE hTimer = CreateWaitableTimer(NULL, TRUE, NULL); 设置对象属性: CreateWaitableTimer创建完成后内核对象处于未触发状态,需要使用API BOOL WINAPI SetWaitableTimer( __in HANDLE hTimer, __in con

线程同步——内核对象实现线程同步——可等待计时器内核对象

1 可等待计时器 2 可等待计时器是这样一种内核对象,他们会在某个指定的时间触发或每隔一段时间触发一次. 5 下面我们来介绍一下创建可等待计时器函数: 6 7 HANDLE CreateWaitableTimer( 8 LPSECURITY_ATTRIBUTES lpTimerAttributes, 9 BOOL bManualReset, 10 LPCSTR lpTimerName ); 11 第一.三个参数我想我也不用介绍了哈,这是创建内核对象基本都会有的参数. 12 第二个参数bManua

Java基础加强之多线程篇(线程创建与终止、互斥、通信、本地变量)

线程创建与终止 线程创建 Thread类与Runnable接口的关系 public interface Runnable { public abstract void run(); } public class Thread implements Runnable { /* What will be run. */ private Runnable target; ...... /** * Causes this thread to begin execution; the Java Virtu

linux 线程创建

一.线程的概念    进程在各个独立的地址空间中运行,进程之间共享数据需要mmap或者进程间通信机制,本节我们学习如何在一个进程的地址空间中执行多个线程.    有些情况需要在一个进程中同时执行多个控制流程,这时候线程就派上了场,如实现一个图形界面的下载软件,需要和用户交互,等待和处理用户的鼠标键盘事件,另一方面又需要同时下载多个文件,等待和处理从多个网络主机发来的数据,这些任务都需要一个" 等待-处理"的循环,可以用多线程实现,一个线程专门 负责与用户交互,另外几个线程每个线程负责和

谈.Net委托与线程——创建无阻塞的异步调用

前言 本文大部分内容来自于mikeperetz的Asynchronous Method Invocation及本人的一些个人体会所得,希望对你有所帮助.原英文文献可以在codeproject中搜索到. 介绍 这篇文章将介绍异步调用的实现机制及如何调用异步方法.大多数.NET开发者在经过delegate.Thread.AsynchronousInvocation之后,通常都会对以上概念产生混淆及误用.实际上,以上概念是.NET2.0版本中对并行编程的核心支持,基于概念上的错误认识有可能导致在实际的

谈.Net委托与线程——创建无阻塞的异步调用(一)

前言 本文大部分内容来自于mikeperetz的Asynchronous Method Invocation及本人的一些个人体会所得,希望对你有所帮助.原英文文献可以在codeproject中搜索到. 介绍 这篇文章将介绍异步调用的实现机制及如何调用异步方法.大多数.NET开发者在经过delegate.Thread.AsynchronousInvocation之后,通常都会对以上概念产生混淆及误用.实际上,以上概念是.NET2.0版本中对并行编程的核心支持,基于概念上的错误认识有可能导致在实际的

linux线程创建、取消、属性设置

创建线程: #include <pthread.h> int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg) 参数:第一个参数为指向线程标识符的指针. 第二个参数用来设置线程属性. 第三个参数是线程运行函数的起始地址. 第四个参数是线程运行函数的参数. int pthread_join(pthread_t thread, void