线程的基本概念
我们知道进程是计算机分配资源的基本单位,计算机会为一个进程分配内存空间和cpu的时间片等资源,而线程则是比进程更小的单位,一个进程可以包含几个线程,其中一个为主线程,在一个进程内的线程中内存资源是共享的,因此在一个进程中的全局变量每个线程都可以访问的,但是每个线程的运行顺序我们是不可控的,因此当几个线程同时访问一个全局变量时便会出现问题,接下来我来贴下一段代码。
代码
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
int a=0;
void * fun1()
{
int i;
for(i=0;i<200000;++i)
{
a+=1;
printf("%d\n",a);
}
return (void *)1;
}
void * fun2()
{
int i;
for(i=0;i<200000;++i)
{
a+=1;
printf("%d\n",a);
}
//
//printf("%d\n",a);
return (void *)2;
}
int main()
{
pthread_t p1,p2;
pthread_create(&p1,NULL,fun1,NULL);
pthread_create(&p2,NULL,fun2,NULL);
printf("%d",a);
void *c,*d;
pthread_join(p1,&c);
pthread_join(p2,&d);
//printf("%d %d %d\n",a,*((int *)c),*((int *)d));
printf("%d\n",a);
}
我们可以看到这段代码创建了两个线程,同时访问一个全局变量,按照我们通常的想法这个输出的最后结果应该是400000,但是有的时候会出现我们意料之外的结果(多运行几次)。
399522
399523
399524
399525
399526
399527
399528
399529
399530
399531
399532
399533
399534
399535
399536
399537
399538
399539
399539
可以看到最后输出的不是400000,这边是出现的问题,出现这个问题的原因:这是因此在我们的cpu在不同线程间进行切换时,当我们的第一个线程的一个寄存器取出我们内存中的a值时,这时发生了线程的切换,便会将第一个线程的状态存入内存中(这时刚取出的a的值便会存入一个栈中,暂时保存第一个线程的资源),这时第二个线程便会运行,当再次切换到第一线程时,便会恢复原来的状态,从栈中取出原来寄存器中的值,继续运行,这时便会存在问题了,因为这时是从栈中去出的a值,这个值还是原来第一次运行后的结果,但是此时我们的第二个线程已经改变了a的值,因此这时我们的第一个线程并没有从第二个线程返回的状态中取a值,因此最终输出的a值便会比我们预期的小。
线程的创建
pthread_create(pthread_t *p,NULL,函数,函数的参数)
创建一个线程,成功返回0,否则返回-1
pthread_join(pthread p,一个指针的地址)
等待一个线程的结束,第二个参数表示线程结束的返回值。
在一个线程中如果使用return 或者 exit(),会退出整个进程
因此我们使用pthread_exit()来退出一个线程
线程的互斥
前面一个例子我们知道使用线程来操作一个全局变量时会出现一些问题,线程互斥便是来解决这个问题的。
原理
表示当一个线程正在使用一个全局变量时我们可以给使用全局变量的这一段代码,加一个锁,不让其他线程访问。
使用的函数
首先创建一个锁变量
pthread_mutex_t a;
初始化
pthread_mutex_init()
加锁
pthread_mutex_lock()
解锁
pthread_mutex_unlock()
销毁锁
pthread_mutex_destory()
网友评论