在多线程编程中必须考虑到不同的线程对同一个变量进行读写访问引起的数据竞争问题。如果线程间没有互斥机制,则不同线程对同一变量的访问顺序是不确定的,有可能导致错误的执行结果。

OpenMP中有两种不同类型的线程同步机制,一种是互斥机制,一种是事件同步机制。


互斥锁机制的设计思路是对一块共享的存储空间进行保护,保证任何时候最多只能有一个线程对这块存储空间进行访问,从而保证数据的完整性,这块存储空间称为“临界区”。可以通过critical、atomic等制导指令以及API中的互斥函数来实现。

事件同步机制的设计思路是控制线程的执行顺序,可以通过设置barrier同步路障、ordered定序区段、matser主线程执行等实现。

互斥锁之critical定义临界区

使用critical定义临界区的格式如下:

#pragma omp critical {需要被保护的代码块}

例如如下示例:

#include<iostream>
#include"omp.h" using namespace std; void main()
{
int sum = 0;
#pragma omp parallel for for (int i = 0; i < 10000; i++)
{
#pragma omp critical
{
sum += i;
}
}
cout << sum << endl;
system("pause");
}

加上critical之后可以保证每次执行结果总是正确的,值为49995000,但如果不加critical语句,结果可能不确定,某次执行的结果为:46932347。

互斥锁之atomic原子操作

制导指令critical可以定义一个任意大小的代码块作为临界区保护,atomic原子操作应用在单条赋值语句中。

#include<iostream>
#include"omp.h" using namespace std; void main()
{
int sum = 0;
#pragma omp parallel for for (int i = 0; i < 10000; i++)
{
{
#pragma omp atomic
sum += i;
}
}
cout << sum << endl;
system("pause");
}

事件同步之barrier(同步路障)

barrier是OpenMP中线程同步的一种方法,在多线程代码块中插入barrier,则先完成计算任务的线程到达此处会等待,直到最后一个线程也完成了计算任务。barrier相当于设置了一个线程的集合点,所有线程都到达之后才能继续往下执行。

#include<iostream>
#include"omp.h" using namespace std; int sum = 0; void Initialization()
{
for (int i = 0; i < 5; i++)
{
sum += i;
}
} void main()
{
#pragma omp parallel
{
Initialization();
#pragma omp barrier
printf("i=%d, thread_id=%d\n", sum, omp_get_thread_num());
}
system("pause");
}

输出:

如果没有添加barrier,由于不同的线程可能同时访问sum变量,存在数据竞争问题,导致输出的sum结果值不确定,其中一次输出为:

事件同步之ordered顺序制导

在循环代码中某些代码的执行需要按规定的顺序执行,比如在一个循环中,一部分的工作可以并行执行,而特定的部分需要按照串行的工作流程依次执行。

#include<iostream>
#include"omp.h" using namespace std; void main()
{
#pragma omp parallel for ordered
for (int i = 0; i < 5; i++)
{
#pragma omp ordered
printf("i=%d, thread_id=%d\n", i, omp_get_thread_num());
}
system("pause");
}

输出:

输出是按照i从小到达的次序依次执行的,如果不加ordered,其中一次输出为:

事件同步之master主线程执行

master制导指令用于指定一个代码块是交由主线程执行,这个代码块虽然位于parallel的并行域中,但是并不会被多个线程执行。

#include<iostream>
#include"omp.h" using namespace std; void main()
{
#pragma omp parallel
{
#pragma omp master
for (int i = 0; i<5; i++)
{
printf("i=%d, thread_id=%d\n", i, omp_get_thread_num());
}
} system("pause");
}

输出:

只有线程0,即主线程执行了该语句,如果不加master指令,其中一次输出为:

OpenMP中的同步和互斥的更多相关文章

  1. Java中线程同步锁和互斥锁有啥区别?看完你还是一脸懵逼?

    首先不要钻概念牛角尖,这样没意义. 也许java语法层面包装成了sycnchronized或者明确的XXXLock,但是底层都是一样的.无非就是哪种写起来方便而已. 锁就是锁而已,避免多个线程对同一个 ...

  2. 转载自~浮云比翼:Step by Step:Linux C多线程编程入门(基本API及多线程的同步与互斥)

    Step by Step:Linux C多线程编程入门(基本API及多线程的同步与互斥)   介绍:什么是线程,线程的优点是什么 线程在Unix系统下,通常被称为轻量级的进程,线程虽然不是进程,但却可 ...

  3. exec函数族,守护进程,线程同步和互斥

    2015.3.2 进程和程序有三点不同:1,存在位置不同,程序:硬盘,磁盘.进程:内存2. 程序是静态的,进程是动态的 执行./a.out -->bash->bash程序调用fork()- ...

  4. Step by Step:Linux C多线程编程入门(基本API及多线程的同步与互斥)

    介绍:什么是线程,线程的优点是什么 线程在Unix系统下,通常被称为轻量级的进程,线程虽然不是进程,但却可以看作是Unix进程的表亲,同一进程中的多条线程将共享该进程中的全部系统资源,如虚拟地址空间, ...

  5. C#中的线程(中)-线程同步

    1.同步要领 下面的表格列展了.NET对协调或同步线程动作的可用的工具:                       简易阻止方法 构成 目的 Sleep 阻止给定的时间周期 Join 等待另一个线程 ...

  6. Windows下C++多线程同步与互斥简单运用

    1.  互斥量,Mutex #include <Windows.h> #include <iostream> using namespace std; DWORD WINAPI ...

  7. UNIX环境高级编程——线程同步之互斥量

    互斥量(也称为互斥锁)出自POSIX线程标准,可以用来同步同一进程中的各个线程.当然如果一个互斥量存放在多个进程共享的某个内存区中,那么还可以通过互斥量来进行进程间的同步. 互斥量,从字面上就可以知道 ...

  8. java同步和互斥【用具体程序说明】

    java同步和互斥[用具体程序说明]            所有对象都自动含有单一的锁,也就是所有对象都有且只有唯一的锁,所以当某个任务(线程)访问一个类A中含有sycnhronized的方法是,那么 ...

  9. Linux驱动之同步、互斥、阻塞的应用

    同步.互斥.阻塞的概念: 同步:在并发程序设计中,各进程对公共变量的访问必须加以制约,这种制约称为同步. 互斥机制:访问共享资源的代码区叫做临界区,这里的共享资源可能被多个线程需要,但这些共享资源又不 ...

随机推荐

  1. 使用SystemC进行硬件仿真

    使用SystemC进行硬件仿真 环境 linux-x86-64 bash g++ 下载解压SystemC SystemC下载地址 解压下载的包 tar zxvf systemc-2.3.3.tar.g ...

  2. POJ 2642 The Brick Stops Here 0-1背包

    poj: http://poj.org/problem?id=2642 大意: 给出n(n<=200)块黄铜合金,还有它们的浓度和价钱.给出若干个个询问使它们在n块中取 M 块 使得这M块合金的 ...

  3. jquery 无刷新上传的小function

    function zll_up(click_id,up_url,text_id,show_id){ this.create = function(){} //当点击指定元素时,创建iframe for ...

  4. Linux系统编程——线程私有数据

    在多线程程序中.常常要用全局变量来实现多个函数间的数据共享.因为数据空间是共享的,因此全局变量也为全部线程共同拥有. 測试代码例如以下: #include <stdio.h> #inclu ...

  5. php面试题7(1、unset变量是删除栈变量,并不删除堆变量)(2、php爬虫特别简单: 可以file_get_contents和直接fopen)

    php面试题7(1.unset变量是删除栈变量,并不删除堆变量)(2.php爬虫特别简单: 可以file_get_contents和直接fopen) 一.总结 1.unset变量是删除栈变量,并不删除 ...

  6. [转载]Ocelot简易教程(三)之主要特性及路由详解

    上篇<Ocelot简易教程(二)之快速开始2>教大家如何快速跑起来一个ocelot实例项目,也只是简单的对Ocelot进行了配置,这篇文章会给大家详细的介绍一下Ocelot的配置信息.希望 ...

  7. BootStrap让两个控件在一行显示

    <div class="row"> <div> <label class="form-inline">参加单位:<in ...

  8. USB 3.0规范中译本 第5章 机械结构

    本文为CoryXie原创译文,转载及有任何问题请联系cory.xie#gmail.com. 本章定义USB 3.0连接器和线缆组件的form, fit 和 function.包括以下方面: • 连接器 ...

  9. USB 3.0规范中译本 第1章 引言

    本文为CoryXie原创译文,转载及有任何问题请联系cory.xie#gmail.com. 1.1 动机(Motivation) Universal Serial Bus (USB) 的原始动机来自于 ...

  10. 解决win7系统不支持16位实模式汇编程序DOS执行的问题

    这学期学习了汇编,在自己电脑上发现,win7的dos不支持16位实模式. 对编程来说,不能执行程序是致命的. 在经过网上搜集资料后,得到一种解决的方法--使用dosbox软件执行 dosbox简单说, ...