【OpenMP】互斥

既然OpenMP涉及并行编程,那么必然涉及到互斥的问题。也就是对同一个变量操作的问题。还是拿《【Java】线程并发、互斥与同步》(点击打开链接)这个抢票的程序作为例子。定义cpu的4个核都对ticket这个变量进行自减,初始为20的ticket变量去到0程序立即停止,不可以出现ticket在同一时间被减2次,导致ticket变成负数的情况。

具体程序如下:

#include <iostream>
#include <omp.h>
using namespace std;
int main()
{
	int ticket=0;//必须被初始化,不然会报错。
	int ticket_statistics[4]={0,0,0,0};
	#pragma omp parallel for num_threads(4) 
	for (ticket=20;ticket>0;ticket--)
	{
		#pragma omp critical
		{
			cout<<"核cpu"<<omp_get_thread_num()<<"拿走了票,票余:"<<(ticket-1)<<endl;
			ticket_statistics[omp_get_thread_num()]++;
		}
	}
	if(ticket==0){
		cout<<"票没了,大家散了吧~得票统计:"<<endl;
		for(int i=0;i<4;i++){
			cout<<"核cpu"<<i<<"得票:"<<ticket_statistics[omp_get_thread_num()]<<"\t";
		}
		cout<<endl;
	}
	return 0;
}

首先ticket必须被初始化,尽管在for循环中给予其复制,但是不对其进行初始化依旧会报错:


OpenMP可以直接利用#pragma omp critical在其#pragma omp parallel for num_threads(线程数目)OpenMP的for循环中定义一段临界区。不用再自己去声明互斥锁之类的。其运行结果如下图所示:


虽然可以见到打印的时候没有按照20-1顺序,但可以肯定的是,ticket变量在多核cpu操作之后,依旧没有出现数据混乱的情况。最后每个cpu还相当规范地平分了这20个tickets。

值得注意的是,#pragma omp critical所定义的临界区仅能够在OpenMP的#pragma omp parallel for num_threads(线程数目)OpenMP的for循环中使用,倘若将这个程序改成while循环程序会报错的。

#include <iostream>
#include <omp.h>
using namespace std;
int main()
{
	int ticket=20;//必须被初始化,不然会报错。
	int ticket_statistics[4]={0,0,0,0};
	#pragma omp parallel num_threads(4) 
	while(ticket>0)
	{
		#pragma omp critical
		{
			ticket--;
			cout<<"核cpu"<<omp_get_thread_num()<<"拿走了票,票余:"<<(ticket-1)<<endl;
			ticket_statistics[omp_get_thread_num()]++;
		}
	}
	if(ticket==0){
		cout<<"票没了,大家散了吧~得票统计:"<<endl;
		for(int i=0;i<4;i++){
			cout<<"核cpu"<<i<<"得票:"<<ticket_statistics[omp_get_thread_num()]<<"\t";
		}
		cout<<endl;
	}
	return 0;
}

运行结果如下:


也就是说,#pragma omp critical必须配合#pragma omp parallel for num_threads(线程数目)OpenMP的for循环使用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值