操作系统 线程并行代码实现
个人理解,极其主观,仅供参考!
关于并发和并行,可以参考文章:多线程是同时执行多个线程的吗。个人理解并发是可以包含并行的概念的。
并发:
多个线程按照一定的顺序逐个占用CPU,执行任务,顺序由操作系统调度。
对于单核处理器而言,其多线程都是并发的。
对于多核处理器而言,其用户级线程是并发的。
并行:
多个线程同时占用CPU多个核心,执行任务(线程数要小于CPU的超线程数)。
对于单核处理器而言,其不存在并行现象。
对于多核处理器而言,其内核心线程是并行的。
**注意:**线程间不争夺系统资源才能产生并行。
代码实现:
环境:win10下使用mingw编译器(在Linux下使用pthread库创建的线程默认是内核级线程——Linux下调用pthread库创建的线程是属于用户级线程还是内核级线程?——其实在windows下也是如此)
int num = 1;
void do1()
{
printf("p1 do1\n");
}
void do2()
{
printf("p2 do2\n");
}
void* funP1(void* arg)
{
while(1)
{
do1();
while(num);
do2();
}
}
void* funP2(void* arg)
{
while(1)
{
sleep(10);
if(num)
{
num = 0;
}
else
{
num = 1;
}
}
}
int main()
{
pid_t p1,p2;
pthread_create(&p1,NULL,funP1,NULL);
pthread_create(&p2,NULL,funP2,NULL);
pthread_join(p1,NULL);
pthread_join(p2,NULL);
return 0;
}
程序输出:
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FTjLEkv9-1623033218332)(C:\Users\Admin\AppData\Roaming\Typora\typora-user-images\image-20210606221848518.png)]](https://i-blog.csdnimg.cn/blog_migrate/929826eaf08d5b39f155e4cce3197dca.png)
程序运行结果如图,这明显与我们的预期不符,如果两个线程同时运行,经过了十秒后,num赋值为0,线程p1不再堵塞在while,do2被调用,应该会看到do2函数运行结果才对。
这里由于采用release版本编译,在线程p1里,由于只有一个读num值的语句,所以编译器进行了优化,每次读寄存器中的值以加快读取速度,其他线程更改了内存中的值,但寄存器的值没有改变,导致卡死在这里。
这时,就要加volatile关键字了,它告诉编译器这是个易变的变量,每次读取这个变量都要从内存中读数据。
加了volatile关键字后,程序的运行结果:
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FV0uj3u8-1623033129668)(C:\Users\Admin\AppData\Roaming\Typora\typora-user-images\image-20210606222928335.png)]](https://i-blog.csdnimg.cn/blog_migrate/ad394ee89bf248519634a253e57c4813.png)
在十秒后,do1 do2被循环调用,再过十秒程序不再打印,循环往复。
印证了,在线程p1执行while循环的时候,p2的sleep函数也在运行,两者并行。
刚接触并发编程的时候,会写一个打印机模型,让两个线程分别打印不同的话:
void* funP1(void* arg)
{
while(1)
{
printf("THREAD1 IS RUNNING\n");
}
}
void* funP2(void* arg)
{
while(1)
{
printf("THREAD2 IS RUNNING\n");
}
}
如果两个线程是并行的,那么程序运行结果会是线程一线程二循环逐次打印,而实际上,程序的输出一段时间是线程一循环打印,一段时间是线程二循环打印,这显然不是并行的,而是并发的。
造成这种现象主要原因是,两个线程都需要占用进程下的同一资源——文件描述符stdout。
其实也不难理解,当两个线程同时更改了同一进程资源,那这个进程资源最后要依据哪个线程而改动呢。处理器可以有多个,但这块内存地址只有一个,当多个处理器通过总线去访问同一块数据时,会造成冲突,OS显然要避免这种事情的发生。
本文探讨了并发和并行的区别,指出并发在单核和多核处理器上的表现,并通过代码示例展示了在多线程环境下,如何实现线程的并行执行。文中提到,由于编译器优化可能导致并发问题,解决方案是使用`volatile`关键字确保变量的正确同步。同时,通过一个打印机模型的例子说明了并发执行时可能出现的现象,解释了并发执行而非并行的原因,涉及线程间的资源竞争问题。
1704





