线程的一点理解

一、线程起源

线程的产生基于通过共享公共的内存空间来交换数据可提高协作进程间的通信效率这一思想。线程是程序执行流的最小单元,是进程中的一个实体,一个标准的线程由线程ID、寄存器集合和堆栈组成。是被系统独立调度和分配的基本单位。线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。由于线程之间的相互制约,致使线程在运行中呈现出间断性。

在某一时刻,进程内只有一个称为控制线程的线程能被执行。当进程的CPU时间片开始时,操作系统根据线程在其他进程线程中的优先级、程序代码的复杂性、该线程被访问的频率等因素为进程选择控制线程。

注意:线程上下文的切换使用系统资源,所以将进程中的线程数保持在为完成预期任务所必须的最少数目是一种良好的编程习惯。

二、线程如何创建?

线程用thread_create函数创建,当pthread_create函数返回时,当前控制线程继续执行pthread_create调用下一条程序指令。

当新线程成为控制线程时,它将执行由调用pthread_create的参数start_routine指定的函数的第一条程序指令。

一旦线程被创建,它将执行直到所有的start_routine程序指令都被执行,或者return语句被执行,或者创建该线程的进程结束。

因为线程之间独立运行,因此给定的线程的确切结束时间是不可知的,称为异步事件。通过等待线程结束并且完成所有的清理工作,pthread_join函数可使线程事件同步,如此线程可以等待另一个线程的结束来实现线程之间的合作。

注意:1.要使用pthread_join和pthread_create函数,必须包含pthread.h头文件.

2.linux下面编译的时候,要用 gcc file.c -lpthread 命令。

下面来看一段代码:

#include<pthread.h>
int main()
{
    pthread_t tid;
    ...
    pthread_create(&tid,NULL,tsub,NULL);
//成功创建返回0;失败,返回大于0的值
    printf("Main thread after pthread_create()\n");
    ...
    return 0;
}
//当新线程成为控制线程的时候,tsub函数开始执行第一条语句printf.
void* tsub(void* arg)
{
    printf("New thread first executable statement\n");
    ...
    return NULL;
}

三、线程如何实现同步?
当进程多于一个执行线程的时候,就有可能出现某个线程试图改变一个变量的值,与此同时另一个线程正试图获得该变量的值。

而我们已经直到,在实际中,两个线程不能同时运行,因为每次只有一个能成为控制线程。所以这个时候,就会产生数据不一致的现象。所谓的数据不一致就是指,由于进程中的一个线程访问共享资源,而另一个线程正在修改共享资源而导致的数据错误。

那么如何避免这种错误呢?我们会采用互斥锁或者互斥量的机制,即通过使用加锁和释放锁的机制,限制在任意给定的时刻共享资源只能由一个线程访问而实现。互斥量可以在访问共享资源之前加锁,访问之后释放。

可以看下面一段代码:

#include<pthread.h>
...
pthread_mutex_t lock;
...
int main(void)
{
    ...
//初始化互斥量函数,成功向进程返回0,失败返回大于0的值
    if(pthread_mutex_init(&lock,NULL)!=0)
        printf("Error initializing mutex lock\n");
    ...
//锁定互斥量函数,成功返回0,失败返回大于0的值
    if(pthread_mutex_lock(&lock)!=0)
        printf("Error locking mutex\n");
    ...
//释放互斥锁的函数,成功返回0,失败返回大于0的值
    if(pthread_mutex_unlock(&lock)!=0)
        printf("Error unlocking mutex\n");
    return 0;
}

附录:

一个完整的多线程的简单程序,以加深理解:

1 #include<pthread.h>
2 #include<stdio.h>
3 #include<unistd.h>
4
5 void* thread(void* argument);
6 intdata;
7 pthread_mutex_t lock;
8
9 intmain()
10 {
11     pthread_t tid;
12     intloop;
13     printf("Primary Thread Started ID  %lu\n",pthread_self());//display the p    rimary thread id;
14     data=0;//Initialize the global share data;
15     /*Initializing the mutex lock*/
16     if(pthread_mutex_init(&lock,NULL)!=0)
17         printf("Error intialializing the mutex lock\n");
18     /*Creating a new thread*/
19     if(pthread_create(&tid,NULL,thread,NULL)!=0)
20         printf("Error creating the thread\n");
21     /*Waiting for the created thread to begin executing*/
22     sleep(1);
for(loop=0;loop<5;loop++)
25     {
26         /*Lock the mutex,update the data,unlock the mutex*/
27         if(pthread_mutex_lock(&lock)!=0)
28             printf("Error locking the mutex\n");
29         data++;
30         /*Dispaly the loop counter and update data value*/
31         printf("Primary thread writing loop %d data %d\n",loop,data);
32
33         if(pthread_mutex_unlock(&lock)!=0)
34             printf("Error unlocking the mutex\n");
35
36         sleep(1);
37     }
38
/*Waiting for the created thread to complete*/
40     if(pthread_join(tid,NULL)!=0)
41         printf("Failed Join\n");
42     printf("Primary Thread Stopped\n");
43
44     return0;
45 }
46
47 void* thread(void* argument)
48 {
49     intloop;//loop counter;
50     printf("Created Thread Started ID %lu\n",pthread_self());
51     sleep(1);
52     for(loop=0;loop<5;loop++)
53     {
if(pthread_mutex_lock(&lock)!=0)
55             printf("Error locking mutex\n");
56         data++;
57
58         printf("Creating thread writing loop %d data %d \n",loop,data);
59         if(pthread_mutex_unlock(&lock)!=0)
60             printf("Error unlocking the mutex\n");
61         sleep(1);
62     }
63
64     printf("Creating Thread Stopped\n");
65     return(NULL);
66 }
67

用gcc thread.c -lpthread 进行编译,注意,-lpthread要放在后面,不然会出现问题。

运行结果:

Primary Thread Started ID 3076118272
Created Thread Started ID 3076115264
Primary thread writing loop 0 data 1
Creating thread writing loop 0 data 2
Primary thread writing loop 1 data 3
Creating thread writing loop 1 data 4
Primary thread writing loop 2 data 5
Creating thread writing loop 2 data 6
Primary thread writing loop 3 data 7
Creating thread writing loop 3 data 8
Primary thread writing loop 4 data 9
Creating thread writing loop 4 data 10
Creating Thread Stopped
Primary Thread Stopped

线程的一点理解,布布扣,bubuko.com

时间: 2024-11-07 10:37:29

线程的一点理解的相关文章

Java中线程同步的理解 - 其实应该叫做Java线程排队

Java中线程同步的理解 我们可以在计算机上运行各种计算机软件程序.每一个运行的程序可能包括多个独立运行的线程(Thread). 线程(Thread)是一份独立运行的程序,有自己专用的运行栈.线程有可能和其他线程共享一些资源,比如,内存,文件,数据库等. 当多个线程同时读写同一份共享资源的时候,可能会引起冲突.这时候,我们需要引入线程"同步"机制,即各位线程之间要有个先来后到,不能一窝蜂挤上去抢作一团. 同步这个词是从英文synchronize(使同时发生)翻译过来的.我也不明白为什么

对事件循环的一点理解

最近工作需要学习了解webworker-threads以应对Javascript多线程处理CPU密集型的可能性:参考文档JavaScript多线程之二 Node.js中的Web Worker; 以下是自己的一次尝试并引发的对于Javascript事件循环机制的一点理解 var Worker = require('webworker-threads').Worker; var worker = new Worker(function() { console.log(33333) postMessa

线程安全和线程不安全理解

线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用.不会出现数据不一致或者数据污染. 线程不安全就是不提供数据访问保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据 ================================================================= 概念: 如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码.如果每次运行结果

我对直接插入排序的一点理解

今天复习排序,发现自己还是没什么长进,不过对于直接插入排序,还是有更深入的一点理解,这里留下点痕迹. 插入排序分为3类,即直接插入排序.二分排序以及希尔排序. 这里简单描述一下直接插入排序的思路.假如你现在是一名新生,早上全学院的学生去文体馆前集合,一个专业一列总队,而你去晚了,不知道自己该站哪,于是需要把自己插入到一个队列中去,这里模拟一下大脑的思路.因为你去晚了,所以你的同学都已经按照高矮顺序站好了,你从队尾开始比较,假如他比你低,ok,没他啥事了,如果他比你高,那他就得往后退,给你留下你站

linuxc线程信号-pthread_cond_wait理解

pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t*mutex)函数 传入的参数mutex用于保护条件,因为我们在调用pthread_cond_wait时,如果条件不成立我们就进入阻塞,但是进入阻塞这个期间,如果条件变量改变了的话,那我们就漏掉了这个条件.因为这个线程还没有放到等待队列上,所以调用pthread_cond_wait前要先锁互斥量, 即调用pthread_mutex_lock(),pthread_cond_wait在把线程

Android measure和layout的一点理解

首先,推荐文章,http://blog.csdn.net/hqdoremi/article/details/9980481,http://www.docin.com/p-571954086.html 我理解measure的作用有2个:一个就是调用子view的measure函数,生成他们的高度和宽度,以便在自己的layout阶段参考:另一个是为父view提供关于自己的测量的width和height(这个宽度和高度往往和子view的测量高度和宽度有关),以便父view在layout阶段参考. lay

关于进程的一点理解

一.什么是进程? 进程包含存储在文件中的一组指令,该文件被读入内存并执行.正在执行的每个唯一的实例被称为进程,并且给它唯一一个标识,成为进程ID,它由操作系统确定.比如你在电脑中同时打开两个QQ,那么这两个程序就叫做进程,而且有两个不同的ID号. 二.进程如何创建? 被称为子进程的新进程由父进程的已存在的进程通过调用fork函数创建. pid=fork();//fork函数回传给pid的值是新进程的ID,数据类型为pid_t,属于int型. 子进程被创建为父进程的一个副本. fork函数在成功时

关于销售的一点理解

[关于销售的一点理解] 1.大多数人存在这样的偏见:销售人员和其他“中间人”很碍事,优良产品应该在生产出来后直接被神奇地分销出去. 这句话反着说,就正确了:销售人员和其他“中间人”很重要,优良产品应该在生产出来后由销售人员分销出去. 2.工程师喜欢制造东西,而不喜欢销售这些东西.但顾客并不会因为你生产了就来买.让顾客来买,并不像看起来那么简单. 3.广告之所以重要,是因为它确实有效.拒绝明显的推销术并不难,但广告不会立刻让你购买产品,而是为以后的购买埋下伏笔. 4.销售人员精心设计活动来改变表象

convertView&amp;setTag方法的一点理解

前言 首先我们要知道setTag方法是干什么的,SDK解释为 Tags Unlike IDs, tags are not used to identify views. Tags are essentially an extra piece of information that can be associated with a view. They are most often used as a convenience to store data related to views in th