Linux编程—线程

本文章为学习笔记,其中有些地方解释的不是那么的好,即本笔记可参考、可借鉴、可指点!


线程定义:
线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。
同一进程中的多条线程将共享该进程中的全部系统资源,如虚拟地址空间,文件描述符和信号处理等等。但同一进程中的多个线程有各自的调用栈(call stack),自己的寄存器环境(register context),自己的线程本地存储(thread-local storage)。
一个进程可以有很多线程,每条线程并行执行不同的任务。

"进程——资源分配的最小单位,线程——程序执行的最小单位"。一个进程中至少含有一条线程。

特点:

进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。

线程有自己的堆栈和局部变量,但线程没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。

线程的创建、退出、等待

int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);
// 返回:若成功返回0,否则返回错误编号

int pthread_exit(void *rval_ptr);//线程的退出

int pthread_join(pthread_t thread, void **rval_ptr);//线程的等待
// 返回:若成功返回0,否则返回错误编号

pthread_t pthread_self(void);//获取线程ID
// 返回:调用线程的ID

当pthread_create成功返回时,由tidp指向的内存单元被设置为新创建线程的线程ID。attr参数用于定制各种不同的线程属性,暂可以把它设置为NULL,以创建默认属性的线程。
新创建的线程从start_rtn函数的地址开始运行,该函数只有一个无类型指针参数arg。如果需要向start_rtn函数传递的参数不止一个,那么需要把这些参数放到一个结构中,然后把这个结构的地址作为arg参数传入。

 线程和进程一样,在没有通过一些手段去控制线程的话,那么他们执行的顺序也是混乱的,互相竞争CPU资源,没有先后顺序。
线程所共享的资源都是他所在当前进程内存空间的数据资源,即如果其中一个线程修改了当前进程的数据值,当另外一个线程或许到该资源的时候就是被之前的线程修改过之后的数据。

代码如下: 

  这种问题就设计到线程同步的问题了,对于多线程程序来说,我们往往需要对这些多线程进行同步。同步(synchronization)是指在一定的时间内只允许某一个线程访问某个资源。而在此时间内,不允许其它的线程访问该资源。我们可以通过互斥锁(mutex),条件变量(condition variable)和读写锁(reader-writer lock)来同步资源。

互斥锁

int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);创建锁

int pthread_mutex_destroy(pthread_mutex_t *mutex);销毁锁;返回:若成功返回0,否则返回错误编号

int pthread_mutex_lock(pthread_mutex_t *mutex);上锁
int pthread_mutex_trylock(pthread_mutex_t *mutex);

int pthread_mutex_unlock(pthread_mutex_t *mutex);解锁
#include <stdio.h>
#include <pthread.h>

int date=0;
pthread_mutex_t mutex;//定义声明锁,且是全局变量

void *func1(void *arg)
{
    pthread_mutex_lock(&mutex);
    int i=5;
    printf("Is t1: %ld thread is create !\n",(unsigned long)pthread_self());
    printf("Is t1:param is %d !\n",*(int *)arg);
    while(i){
        i--;
        printf("this is ti1 = %d , t1 date = %d !\n",i,date++);
        //sleep(1);
    }
    pthread_mutex_unlock(&mutex);
    pthread_exit(NULL);
}
void *func2(void *arg)
{
    pthread_mutex_lock(&mutex);
    int i=5;
    printf("Is t2: %ld thread is create !\n",(unsigned long)pthread_self());
    printf("Is t2:param is %d !\n",*(int *)arg);
    while(i){
        i--;
        printf("this is ti2 = %d , lock t2 date = %d !\n",i,date++);
        sleep(1); 
    }
    pthread_mutex_unlock(&mutex);
    pthread_exit(NULL);
}
void *func3(void *arg)
{
    pthread_mutex_lock(&mutex);
    int i=5;
    printf("Is t3: %ld thread is create !\n",(unsigned long)pthread_self());
    printf("Is t3:param is %d !\n",*(int *)arg);
    while(i){
        i--;
        printf("t3 date = %d !\n",i,date++);
        sleep(3);
    }
    pthread_mutex_unlock(&mutex);
    pthread_exit(NULL);
}
int main()
{
    int ret1,ret2,ret3;
    int param=100;
    pthread_t t1,t2,t3;
    pthread_mutex_init(&mutex,NULL);
    ret1=pthread_create(&t1,NULL,func1,(void *)&param);
    if(ret1==0){
        printf("main : creat t1 pthread is suceaaed !\n");
    }
    ret2=pthread_create(&t2,NULL,func2,(void *)&param);
    if(ret2==0){
        printf("main : creat t2 pthread is suceaaed !\n");
    }
    ret3=pthread_create(&t3,NULL,func3,(void *)&param);
    if(ret3==0){
        printf("main : creat t3 pthread is suceaaed !\n");
    }
    printf("main : pthread id is %ld !\n",(unsigned long)pthread_self());
    pthread_join(t1,NULL);
    pthread_join(t2,NULL);
    pthread_join(t3,NULL);
    pthread_mutex_destroy(&mutex);//销毁锁
    return 0;
}

执行结果

 针对多线程的程序来说,当他们共享一个进程的内存空间时,又因为线程之间时相互竞争CPU资源;当其中一个线程设置了一个条件(该条件来自于他们共享的内存空间的时候),而导致设置了条件的那个线程因没有获取该条件而无法执行该条件时的解决方法!

 条件

int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);//创建条件

int pthread_cond_destroy(pthread_cond_t *cond);//销毁条件
// 返回:若成功返回0,否则返回错误编号

int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, cond struct timespec *restrict timeout);//用于广播等待
// 条件等待;返回:若成功返回0,否则返回错误编号

int pthread_cond_signal(pthread_cond_t *cond);//条件触发
int pthread_cond_broadcast(pthread_cond_t *cond);//条件广播触发
// 返回:若成功返回0,否则返回错误编号

pthread_cond_wait等待条件变为真。如果在给定的时间内条件不能满足,那么会生成一个代表一个出错码的返回变量。传递给pthread_cond_wait的互斥量对条件进行保护,调用者把锁住的互斥量传给函数。函数把调用线程放到等待条件的线程列表上,然后对互斥量解锁,这两个操作都是原子操作。这样就关闭了条件检查和线程进入休眠状态等待条件改变这两个操作之间的时间通道,这样线程就不会错过条件的任何变化。pthread_cond_wait返回时,互斥量再次被锁住。

pthread_cond_timedwait函数的工作方式与pthread_cond_wait函数类似,只是多了一个timeout。timeout指定了等待的时间,它是通过timespec结构指定。

代码解释

互斥锁—死锁 


课外笔记

fflush()

fflush是一个在C语言标准输入输出库中的函数,功能是冲洗流中的信息,该函数通常用于处理磁盘文件。fflush()会强迫将缓冲区内的数据写回参数stream 指定的文件中。

在使用多个输出函数连续进行多次输出时,有可能发现输出错误。因为下一个数据再上一个数据还没输出完毕,还在输出缓冲区中时,下一个printf就把另一个数据加入输出缓冲区,结果冲掉了原来的数据,出现输出错误。 在 prinf();后加上fflush(stdout); 强制马上输出,避免错误。

定义函数:int fflush(FILE * stream);
函数说明:fflush()会强迫将缓冲区内的数据写回参数stream指定的文件中,如果参数stream为NULL,fflush()会将所有打开的文件数据更新。
返回值:成功返回0,失败返回EOF,错误代码存于errno中。
fflush()也可用于标准输入(stdin)和标准输出(stdout),用来清空标准输入输出缓冲区。
stdin是standard input的缩写,即标准输入,一般是指键盘;标准输入缓冲区即是用来暂存从键盘输入的内容的缓冲区。stdout是standard output 的缩写,即标准输出,一般是指显示器;标准输出缓冲区即是用来暂存将要显示的内容的缓冲区。
清空标准输出缓冲区,刷新输出缓冲区,即将缓冲区的东西输出到屏幕上 
如果圆括号里是已写打开的文件的指针,则将输出缓冲区的内容写入该指针指向的文件,否则清除输出缓冲区。
这里的stdout是系统定义的标准输出文件指针,默认情况下指屏幕,那就是把缓冲区的内容写到屏幕上。
 

>>test.ret.txt &

将执行文件的结果追加到test.ret.txt文件里面;

& 可看作是将该运行的程序放在后台运行

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值