对比进程与线程的区别
(1)进程是资源的分配和调度的一个独立单元,而线程是CPU调度的基本单元
(2)同一个进程中可以包括多个线程,并且线程共享整个进程的资源(寄存器、堆栈、上下文),一个进程至少包括一个线程。
(3)进程的创建调用fork或者vfork,而线程的创建调用pthread_create,进程结束后它拥有的所有线程都将销毁,而线程的结束不会影响同个进程中的其他线程的结束
(4)线程是轻两级的进程,它的创建和销毁所需要的时间比进程小很多,所有操作系统中的执行功能都是创建线程去完成的
(5)线程中执行时一般都要进行同步和互斥,因为他们共享同一进程的所有资源
(6)线程有自己的私有属性TCB,线程id,寄存器、硬件上下文,而进程也有自己的私有属性进程控制块PCB,这些私有属性是不被共享的,用来标示一个进程或一个线程的标志
总结:
1, 在Linux下并不区分线程与进程,也就是说系统并不认为自己有线程这个东西,创建线程的函数pthread_create(pthread_t * p,NULL, (void*)func(void*arg) ,NULL); 是调用了POSIX的库函数,不是系统调用。也就是利用posix库函数模拟出来了线程。
2, 线程ID有两种:
1> 放在线程PCB中的pid,供系统调用时使用(轻量级进程)
2> 在创建线程时的返回型参数,pthread_t id,供编程时使用,
如线程等待函数,pthread_join(pthread_t id , NULL);
该函数用于等待进程并回收进程资源。
3,证明:同一进程内的多个线程公用同一块虚拟地址空间
答:
创建多个线程,去修改同一全局变量,最终每个进程得到的变量都一样。
使用fork创建子进程,父子进程同时修改全局变量,最终得的值不一样,这是因为子进程独自拥有一份虚拟地址空
间,在变量发生改变时,通过改变页表,完成写时拷贝。
4,为啥要有互斥
1> 多进程,多线程执行的先后顺序不同,切换的时机也不确定。
2> 多进程,多线程访问变量的动作不是原子的。
5,如何避免死锁
1> 短:临界区代码简短明了。
2> 平:临界区代码逻辑清晰,无复杂的函数调用。
3> 快:临界区代码执行速度快。
结线程属性
线程属性结构如下:
typedef struct
{
int detachstate; 线程的分离状态
int schedpolicy; 线程调度策略
structsched_param schedparam; 线程的调度参数
int inheritsched; 线程的继承性
int scope; 线程的作用域
size_t guardsize; 线程栈末尾的警戒缓冲区大小
int stackaddr_set;
void* stackaddr; 线程栈的位置
size_t stacksize; 线程栈的大小
}pthread_attr_t;
1、线程的分离状态
线程的分离状态决定一个线程以什么样的方式来终止自己。在默认情况下线程是非分离状态的,这种情况下,原有的线程等待创建的线程结束。只有当pthread_join()函数返回时,创建的线程才算终止,才能释放自己占用的系统资源。
而分离线程不是这样子的,它没有被其他的线程所等待,自己运行结束了,线程也就终止了,马上释放系统资源。程序员应该根据自己的需要,选择适当的分离状态。所以如果我们在创建线程时就知道不需要了解线程的终止状态,则可以pthread_attr_t结构中的detachstate线程属性,让线程以分离状态启动。
2、线程的继承性
继承性决定调度的参数是从创建的进程中继承还是使用在schedpolicy和schedparam属性中显式设置的调度信息。Pthreads不为inheritsched指定默认值,因此如果你关心线程的调度策略和参数,必须先设置该属性。
继承性的可能值是PTHREAD_INHERIT_SCHED(表示新现成将继承创建线程的调度策略和参数)和PTHREAD_EXPLICIT_SCHED(表示使用在schedpolicy和schedparam属性中显式设置的调度策略和参数)。
如果你需要显式的设置一个线程的调度策略或参数,那么你必须在设置之前将inheritsched属性设置为PTHREAD_EXPLICIT_SCHED.
线程的同步与互斥
1,为啥要有互斥
多进程,多线程执行的先后顺序不同,切换的时机也不确定。
多进程,多线程访问变量的动作不是原子的。
例如:i++ cpu完成时会有三步操作,任意切换会导致出错
2,为啥要有同步:
多进程,多线程执行的先后顺序不同,切换的时机也不确定。
想要不同的线程为我们完成具有顺序的部分任务,就必须是使其具有顺序。
使用gdb调试多线程
给临界资源加锁,保证原子性
#include<stdio.h>
2 #include<pthread.h>
3 #include<unistd.h>
4 int count =0;
5 pthread_mutex_t lock=PTHREAD_MUTEX_INITIALIZER;
6 void * thread_run(void*arg)
7 {
8 int i=0;
9 while(i<50000000)
10 {
11 pthread_mutex_lock(&lock);
12 count++;
13
14 pthread_mutex_unlock(&lock);
15 i++;
16 }
17
18
19
20
21 }
22 int main ()
23 {
24 pthread_t tid1,tid2;
25 pthread_create(&tid1,NULL,thread_run,NULL);
26 pthread_create(&tid2,NULL,thread_run,NULL);
27 pthread_join(tid1,NULL);
28 pthread_join(tid2,NULL);
29 printf(" res count is %d\n",count);
30 return 0;
31 }