APUE学习笔记——第十一章 线程

论坛 期权论坛     
选择匿名的用户   2021-5-22 14:50   144   0
<span style="white-space:pre"></span>典型的UNIX进程可以看成只有一个控制线程:一个进程在同一时刻只能做一件事情。有了多个控制线程之后,在程序设计时可以把进程设计成在同一时刻能够做不止一件事,每个线程处理各自独立的任务。使用线程有很多好处:
<br> (1)、通过为每种事件类型的处理分配单独的线程,能够简化处理异步事件的代码。
<br> (2)、多个线程自动地可以访问相同的存储地址空间和文件描述符
<br> (3)、将一个问题分解为多个程序,改善整个程序的吞吐量
<br>
<p>(4)、使用多线程改善交互程序的响应时间。</p>
<p>1、线程标识<br> <span style="white-space:pre"></span>就像每个进程有一个进程ID一样,每个线程也有一个线程ID。进程ID在整个系统中是唯一的,但是线程ID不同,线程ID只在它所属的进程环境中有效。进程ID使用pid_t数据类型来表示,是一个非负整数。线程ID则是用pthread_t数据类型来表示,实现的时候可以用一个结果来代表pthread_t数据类型,所以可移植的操作系统实现不能把它当作整数处理。必须使用函数来对两个线程ID进程比较:<br> #include &lt;pthread.h&gt;<br> int pthread_equal(pthread_t tid1,pthread_t tid2)     返回值:若相等则返回非0值,否则返回0<br> 线程可以通过调用pthread_self函数获取自身的线程ID<br> #include &lt;pthread.h&gt;<br> pthread_t pthread_self(void);<br> </p>
<p>2、线程的创建</p>
<p>   <span style="white-space:pre"> </span>新增的线程可以通过调用pthread_create函数创建:<br> #include &lt;pthread.h&gt;<br> int pthread_create(pthread_t *tid,const pthread_attr_t *attr,void* (*start_rtn)(void),void* arg)<br> 返回值:成功返回0,否则返回错误编号<br> <span style="white-space:pre"></span>当pthread_create成功返回时,由tid指向的内存单元被设置为新创建线程的线程ID,attr参数用于指定各种不同的线程属性,可以暂时设置为NULL,创建默认属性的线程,新创建的线程从start_rtn函数的地址开始运行,该函数只有一个无类型指针参数arg,如果需要向start_rtn函数传递的参数不止一个,则需要把这些参数放到一个结构体中,然后把结构体的地址作为arg参数传入。<br> </p>
<p></p>
<pre class="blockcode"><code class="language-cpp">#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;unistd.h&gt;
#include &lt;pthread.h&gt;

void printid(const char *str){
    printf(&#34;%s, pid: %d, tid: %u\n&#34;,str,getpid(),pthread_self());
}

void * thread_func(void *arg){
    printid(&#34;new thread: &#34;);
    return (void*)0;
}

int main(){
    pthread_t ntid;
    pthread_create(&amp;ntid,NULL,thread_func,NULL);
    printid(&#34;main thread: &#34;);
    sleep(2);
    exit(0);
}
</code></pre>由于pthread库不是Linux系统默认的库,连接时需要使用库libpthread.a,所以在使用pthread_create创建线程时,在编译中要加-lpthread参数。
<p></p>
<p>例如:gcc thread.c -lpthread -o thread</p>
<p>3、线程终止<br> <span style="white-space:pre"></span>如果进程中的任一线程调用exit,_Exit或_exit,那么整个进程就会终止。单个线程可以通过下列三种方式退出,在不终止整个进程的情况下停止它的控制了。<br> (1)、线程只是从启动例程中返回,返回值是线程的退出码<br> (2)、线程可以被统一进程中的其他线程取消<br> (3)、线程调用pthread_exit函数<br> #include &lt;pthread.h&gt;<br> void pthread_exit(void* rval_ptr)<br> rval_ptr是一个无类型指针,与传递启动例程的单个参数类似。进程中的其他线程可以通过调用pthread_join函数访问到这个指针。<br> #include &lt;pthread.h&gt;<br> int pthread_join(pthread_t tid, void* *rval_ptr)返回值:成功返回0,否则返回错误编号。<br> <span style="white-space:pre"></span>需要注意的是pthread_create和pthread_exit函数的无类型指针参数能够传递的数值可以不止一个,该指针可以传递包含复杂信息的结构地址,这个结构必须所使用的内存必须在调用者用完以后必须仍然有效,否则会出现无法访问或非法。例如在线程的栈上分配了该结构,例如下面程序,参数不正确使用,导致结果错误,<br> 例如:<br> </p>
<p></p>
<pre class="blockcode"><code class="language-cpp">#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;unistd.h&gt;
#include &lt;pthread.h&gt;

struct foo{int a,b,c,d;};

void print(const char *str,const struct foo *fp){
    puts(str);
    printf(&#34;addr: 0x%x\n&#34;,(unsigned int)fp);
    printf(&#34;a &#61; %d\n&#34;,fp-&gt;a);
    printf(&#34;b &#61; %d\n&#34;,fp-&gt;b);
    printf(&#34;c &#61; %d\n&#34;,fp-&gt;c);
    printf(&#34;d &#61; %d\n&#34;,fp-&gt;d);
}

void * thread_func1(void *arg){
    struct foo foo &#61; {1,2,3,4};//线程栈上分配内存
    print(&#34;Thread 1:&#34;,&amp;f
分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:3875789
帖子:775174
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP