线程调用

线程创建。

  –在进程中只有一个控制线程

  –程序开始运行的时候每个进程只有一个线程,它是以单线程方式启动的,在创建多个线程以前,进程的行为与传统的进程没有区别。

  –gcc在链接的时候需要增加-lpthread选项。

  –创建一个线程调用pthread_create函数。

#include <pthread.h>

int pthread_create(pthread_t *thread,const pthread_attr_t *attr, void *(*start_routine)(void*), void *arg);

如果pthread_create成功返回,由thread指向的内存单元被设置为新创建线程的线程ID。

attr参数用于定制各种不同的线程属性。

新创建的线程从start_rtn函数地址开始执行,该函数只有一个void *参数,如果需要向start_rtn函数传递多个参数,就需要把这些参数放到一个结构中,然后把这个结构的地址做为void *传入。

线程创建的时候不能保证哪个先运行。

pthread函数调用失败,返回errno

  –注意:每个线程都拥有一份errno副本,不同的线程拥有不同的errno

pthread_create例子

gcc链接时需要加-lpthread选项

void *func(void *arg)
{
    printf("pthread start\n");
    return NULL;
}
int main(int arg, char * args[])
{
    pthread_t thr_d;
    int err = pthread_create(&thr_d, NULL, func, NULL);
    if (err != 0)
    {
        printf("create pthread failed\n");
    }
    else
    {
        printf("create pthread success\n");
    }
    sleep(1);
    return 0;
}

线程终止。

  –任一线程调用了exit函数,整个进程就会终止。

  –如果信号默认动作是终止进程,那么信号发送到该线程,整个进程也会被终止。

单个线程通过以下三种方式退出

  –线程只是从启动函数中返回,返回值是线程的退出码。

  –线程可以被同一进程中的其他线程取消。

  –线程调用pthread_exit。

void pthread_exit(void *arg);

arg是个无类型指针,该指针会被其他线程调用pthread_join捕捉。

pthread_exit例子

void *func(void *arg)
{
    printf("pthread start\n");
    static int i = 1;
    pthread_exit(&i);
}
int main(int arg, char * args[])
{
    pthread_t thr_d;
    pthread_create(&thr_d, NULL, func, NULL);
    sleep(1);
    return 0;
}

int pthread_join(pthread_t th, void **thr_return);。

pthread_join函数用于挂起当前线程,直至th指定的线程终止为止。

如果另一个线程返回值不是NULL,则保存在thr_return地址中。

一个线程所使用的内存资源在应用pthread_join调用之前不会被重新分配,所以对于每个线程必须调用一次pthread_join函数。

其他线程不能对同一线程再应用pthread_join调用。

pthread_join例子

void *func(void *arg)
{
    printf("pthread start\n");
    static int i = 0;
    sleep(2);
    pthread_exit(&i);
}
int main(int arg, char * args[])
{
    pthread_t thr_d;
    pthread_create(&thr_d, NULL, func, NULL);
    void *p;
    pthread_join(thr_d, &p);
    int *pi = (int *)p;
    printf("thread exit %d\n", *pi);
    return 0;
}

int pthread_detach(pthread_t th);

pthread_detach函数使线程处于被分离状态。

对于被分离状态的线程,不需要调用pthread_join,如果其他线程调用pthread_join失败,返回EINVAL。

如果不等待一个线程,同时对线程的返回值不感兴趣,可以设置这个线程为被分离状态,让系统在线程退出的时候自动回收它所占用的资源。

一个线程不能自己调用pthread_detach改变自己为被分离状态,只能由其他线程调用pthread_detach。

pthread_detach例子

void *func(void *arg)
{
    printf("pthread start\n");
    pthread_exit(NULL);
}
int main(int arg, char * args[])
{
    pthread_t thr_d;
    pthread_create(&thr_d, NULL, func, NULL);
    pthread_detach(thr_d);
    sleep(1);
    return 0;
}

int pthread_cancel(pthread_t th);

pthread_cancel函数允许一个线程取消th指定的另一个线程。

函数成功,返回0,否则返回非0。

pthread_cancel例子

void *func(void *arg)
{
    printf("pthread start\n");
    while(1)
    {
        printf("thread is running\n");
        sleep(1);
    }
    pthread_exit(NULL);
}
int main(int arg, char * args[])
{
    pthread_t thr_d;
    pthread_create(&thr_d, NULL, func, NULL);
    pthread_detach(thr_d);
    sleep(6);
    pthread_cancel(thr_d);
    sleep(6);
    printf("end\n");
    return 0;
}

int pthread_equal(pthread_t th1,pthread_t th2);

pthread_equal函数比较th1与th2是否为同一个线程,由于不可以将pthread数据类型认为是整数,所以也不能用比较整数的方式比较pthread_t。

如果th1与th2相同,函数返回非0值,如果不同函数返回0。

线程属性

  –以前调用pthread_create传入的attr参数都是空指针,而不是指向pthread_attr_t结构的指针。

  –可以使用pthread_attr_t结构修改线程默认属性,并把这些属性与创建的线程联系起来

  –可以使用pthread_attr_init函数初始化pthread_attr_t结构。

  –调用pthread_attr_init以后,pthread_arrt_t的结构所包含的内容就是操作系统实现支持线程所有属性的默认值。如果要修改其中个别属性的值,需要调用其他函数。

int pthread_attr_destroy(pthread_attr_t *attr);

int pthread_attr_init(pthread_attr_t *attr);

函数pthread_attr_init初始化attr结构。

函数pthread_attr_destroy释放attr内存空间。

pthread_attr_t的结构对于应用程序来讲是不透明的,应用程序不需要了解有关结构的内部组成。

以前介绍了pthread_detach函数的概念,可以通过pthread_attr_t在创建线程的时候就指定线程属性为detach,而不用创建以后再去修改线程属性。

int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate); 。

函数pthread_attr_setdetachstate把线程属性设置为下面两个合法值之一



说明


PTHREAD_CREATE_DETACHED


设置线程为分离状态


PTHREAD_CREATE_JOINABLE


设置线程为正常状态

pthread_setdetachstate例子

void *func(void *arg)
{
    printf("pthread start\n");
    while(1)
    {
        printf("thread is running\n");
        sleep(1);
    }
    pthread_exit(NULL);
}
int main(int arg, char * args[])
{
    pthread_t thr_d;
    pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    pthread_create(&thr_d, &attr, func, NULL);
    pthread_attr_destroy(&attr);
    sleep(2);
    printf("end\n");
    return 0;
}

复制去Google翻译翻译结果

时间: 2024-10-11 21:18:18

线程调用的相关文章

async 与 await 线程调用顺序

用async做一个多线程下载并在datagridview中即时更新,运行时在达到4个线程同时下载时界面卡顿,多次尝试后是不知道async与await线程调用顺序造成. 进入async方法后在调用await之前代码都在主线程(调用线程)中运行,调用await时及之后的async方法代码将另起线程运行该部分代码,而主线程在遇到await后回到主线程继续执行async后的代码. 将async方法通过声明委托后用begininvoke调用后解决.

Atitit.swt&#160;线程调用ui控件的方法

Atitit.swt 线程调用ui控件的方法 1 SwingUtilities.invokeLater1 2 display.asyncExec方法1 3  display.timerExec(500,timer);2 4 .但有时候并不一定要程序执行时就要定时检测,有时需要外部事情激发这就出现了第2种解决方案,写一个内置类,可以放在事件监听的方法中,然后激发:2 5 参考3 1   SwingUtilities.invokeLater SwingUtilities.invokeLater(ne

python获得线程调用函数的返回值

threading.Thread 并没有显式的提供获取线程调用函数返回值的方法,需求自己实现. 使用数据库是一个办法: 可以让子线程将数据写到数据库中,消费线程再去数据库中读取数据: 如果不想用数据库,可以使用类的全局变量来做传递, 示例代码如下: import os import threading class SubThread(): data = {} def __init__(self): ... def execute_func(self, key): # 执行各种操作 ... ret

如何跨线程调用Windows窗体控件

通过一个子线程来操作主线程中的控件,但是,这样作会出现一个问题(如图1所示),就是TextBox控件是在主线程中创建的,在子线程中并没有对其进行创建,也就是从不是创建控件的线程访问它.那么,如何解决跨线程调用Windows窗体控件呢?可以用线程委托实现跨线程调用Windows窗体控件.下面将上一个例子进行一下改动.代码如下: using System; using System.Collections.Generic; using System.ComponentModel; using Sys

C#跨线程调用

项目上线测试时客户提出表单跳转到指定位置(表单比较长).当时以为这个就是添加几行代码几分钟的事情,随口答应了.但是到做的时候才发现事情远没有那么简单,测试发现将焦点给指定位置的控件表单可自动滑动到指定位置,但是在事件里面调用控件的Focus方法始终没有任何效果.遂觉得是否控件未初始话无法设置Focus所致,新开一个独立线程等待表单初始化完成时进行跳转.但是又发现“线程间操作无效”,原来是由于Windows安全策略新线程无法操作UI主线程,网上终于找到跨线程操作的示例.依葫芦画瓢,通过跨线程调用,

C# 跨线程调用控件

在C# 的应用程序开发中, 我们经常要把UI线程和工作线程分开,防止界面停止响应.  同时我们又需要在工作线程中更新UI界面上的控件, 下面介绍几种常用的方法 阅读目录 线程间操作无效 第一种办法:禁止编译器对跨线程访问做检查 第二种办法: 使用delegate和invoke来从其他线程中调用控件 第三种办法: 使用delegate和BeginInvoke来从其他线程中控制控件 第四种办法: 使用BackgroundWorker组件 源代码下载 线程间操作无效 界面上有一个button和一个la

c#中跨线程调用windows窗体控件

c#中跨线程调用windows窗体控件解决. 我们在做winform应用的时候,大部分情况下都会碰到使用多线程控制界面上控件信息的问题.然而我们并不能用传统方法来做这个问题,下面我将详细的介绍.首先来看传统方法: public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { Thread thre

多线程总结之旅(112):跨线程调用控件的几种方式

本来是写完线程池就结束多线程总结之旅系列的,但是想想平时在项目中用到线程仅仅不够的,为什么这么说呢?举个例子:我们有一个函数,它的功能就是加载数据,然后绑定到datagridview.现在我们开启一个线程去执行这个函数.结果可想而知,它会报错:提示线程无法访问...之类的话.为什么报错呢?因为你在开启的线程中操作了datagridview控件,也就是你跨线程调用控件了. 那么我们应该怎么跨线程调用控件呢?下面我就把我总结的几种方法奉献给各位. 跨线程调用控件的几种方法: 1.方法一:Contro

c#中跨线程调用windows窗体控件 .我们在做winform应用的时候,大部分情况下都会碰到使用多线程控制界面上控件信息的问题。然而我们并不能用传统方法来做这个问题,下面我将详细的介绍。

首先来看传统方法: public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { Thread thread = new Thread(ThreadFuntion); thread.IsBackground = true; thread.Start(); } private void Thread