操作系统与系统编程——线程(4)

 


目录

线程

线程基本原理

        与进程的区别

线程原语:

线程同步

一个线程创建和回收的实例


 

线程

线程基本原理

 

https://img-blog.csdn.net/20150116114002794?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvSVRlcl9aQw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center

进程fork,子进程会复制(读时共享、写时复制)父进程的虚拟内存空间,从逻辑控制流的角度来说,fork创建的子进程开始执行的位置是fork函数返回的位置

上下文切换:(子进程复制了父进程的各种(文件描述符表,信号控制信息等信息),故要进行这些信息+进程运行时信息(寄存器、进程运行信息)的备份。

 

进程上下文切换保存的内容有

页表 -- 对应虚拟内存资源。(父子进程内存独立)

文件描述符表/打开文件表 -- 对应打开的文件资源(与进程相关的数据结构)

寄存器 -- 对应运行时数据

进程运行信息。

线程:

并发的本质是同时运行的多个逻辑流。并发编程要解决的一个很重要的问题就是对资源的并发访问的问题。而两个进程恰恰很难在逻辑上表示共享资源(进程间通信)。

一个进程的所有线程都是共享这个进程的同一个虚拟地址空间的,从线程的角度它们看到的物理资源是一样的,这样就可以通过共享变量的方式来表示共享资源,也就是直接共享内存的方式解决了线程通信的问题。而线程也表示一个独立的逻辑流,支持并发。

进程上下文切换(线程运行时的数据):线程的id、寄存器中的值、栈数据

从这个角度,线程更像寄存器+栈。

与进程的区别

进程是资源分配的最小单位,线程是CPU调度的最小单位。

2)进程有独立的系统资源,而同一进程内的线程共享进程的大部分系统资源,包括堆、代码段、数据段,每个线程只拥有一些在运行中必不可少的私有属性,比如tcb,线程Id,栈、寄存器。

3)一个进程崩溃,不会对其他进程产生影响;而一个线程崩溃,会让同一进程内的其他线程也死掉。

4)进程在创建、切换和销毁时开销比较大,而线程比较小。进程创建的时候需要分配系统资源,而销毁的的时候需要释放系统资源。进程切换需要分两步:切换页目录、刷新TLB以使用新的地址空间;切换内核栈和硬件上下文(寄存器);而同一进程的线程间逻辑地址空间是一样的,不需要切换页目录、刷新TLB。

5)进程间通信比较复杂,而同一进程的线程由于共享代码段和数据段,所以通信比较容易。

线程原语:

线程创建:

函数返回,当前线程继续往下执行,新线程从传入的函数指针start_routine开始执行。函数返回时则线程退出。

 

获取调用线程tid

线程退出:

线程回收:

线程取消:

线程分离:

比较两个线程是否相等:

线程终止方式:

线程安全:

  1. 如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。
  2. 线程安全问题都是由全局变量静态变量引起的。
  3. 若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则的话就可能影响线程安全。
  4. 对于线程不安全的对象我们可以通过如下方法来实现线程安全:

线程同步

互斥量(锁):

锁机制是同一时刻只允许一个线程执行一个关键部分的代码。

死锁:

读写锁:

条件变量

条件变量是利用线程间共享全局变量进行同步的一种机制。条件变量上的基本操作有:触发条件(当条件变为 true 时);等待条件,挂起线程直到其他线程触发条件。

必须和互斥锁进行配合使用

生产者消费者模型,生产者对带有头节点的链表头插方式push_front生产数据,消费者调用pop_front消费数据。而生产者可能动作比较慢,这时就会有问题。

生产者生产一个数据时间,消费者可能迫切需求。因此,一直轮寻申请锁资源,以便进行消费。所以就会产生多次不必的锁资源申请释放动作。影响系统性能。

信号量   

参见进程:

一个线程创建和回收的实例

/*************************************************************************
	> File Name: dm06_thread_attributes.c
	> Author: ma6174
	> Mail: ma6174@163.com 
	> Created Time: 2018年09月11日 星期二 19时43分03秒
 ************************************************************************/

#include<stdio.h>
#include<pthread.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>

void *th_fun(void*arg)
{
	int n = 20;
	while(n--)
	{
		printf("%x %d\n",(int)pthread_self(),n);
		sleep(1);
	}
	return (void*)1;
}

int main()
{
	pthread_t tid;
	pthread_attr_t attr;//attr is rubbish
	int err;

	pthread_attr_init(&attr);
	pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);

	pthread_create(&tid,&attr,th_fun,NULL);

	err = pthread_join(tid,NULL);

	while(1)
	{
		if(err != 0){
			printf("%s\n",strerror(err));
			sleep(10);
			pthread_exit((void*)1);
		}
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值