Pthreads Hello World,忙等待,互斥量
▶ 一个简单的 Pthreads 程序(不按照《并行程序设计导论》中的程序来写)
● 代码
- #include <stdio.h>
- #include <pthread.h>
- #pragma comment(lib, "pthreadVC2.lib")
- const int thread = ;
- void* work(void* input)
- {
- if (input == nullptr)
- printf("nullptr!\n");
- else
- printf("%d\n", *((int *)input)); // 将得到的 void * 参数转化为需要的数据类型再进行使用
- return nullptr;
- }
- int main()
- {
- pthread_t array[thread]; // 产生各线程的 pthread_t 对象
- int i, list[thread];
- for (i = ; i < thread; i++)
- {
- list[i] = i * ;
- pthread_create(&array[i], nullptr, work, &list[i]); // 生成各线程来运行函数 work(),函数参数为 list[i],没有线程属性参数
- }
- for (i = ; i < thread; i++)
- pthread_join(array[i], nullptr); // 终止各线程
- getchar();
- return ;
- }
● 输出结果:8 个乱序的数字
● 用到的定义,pthread.h
- typedef struct
- {
- void * p; // Pointer to actual object
- unsigned int x; // Extra information - reuse count etc
- } ptw32_handle_t;
- typedef ptw32_handle_t pthread_t;
- typedef struct pthread_attr_t_ * pthread_attr_t;// 没有其他地方提到了 struct pthread_attr_t_ 的成员
- PTW32_DLLPORT int PTW32_CDECL pthread_create(
- pthread_t * tid, // 输入 pthread_t 的指针
- const pthread_attr_t * attr, // pthread_t 对象的属性
- void *(PTW32_CDECL *start) (void *), // 工作函数,输入参数和返回类型均为 void *
- void *arg // 工作函数的输入参数
- );
- PTW32_DLLPORT int PTW32_CDECL pthread_join(
- pthread_t thread, // 需要等待终止的 pthread_t 对象,注意不是指针
- void **value_ptr // ?
- );
▶ 使用直接访问、忙等待和互斥量计算 π 的值,使用公式 π / 4 = 1 - 1 / 3 + 1 / 5 - 1 / 7 + ...,Mathematica 的精确结果为 0.78539816339744830962
● 直接访问临界区,代码
- #include <stdio.h>
- #include <pthread.h>
- #include <time.h>
- #pragma comment(lib, "pthreadVC2.lib")
- const int count = , thread = ;// 使用 8 个线程来计算 2^30 项
- double sum;
- void* threadSum_naïve(void* rank)
- {
- const long long localRank = (long long)rank;// 使用 long long 类型,可以直接与 void* 相互转化
- const int localCount = count / thread;
- int i;
- double sign;
- if (localCount * localRank % )
- sign = -1.0;
- else
- sign = 1.0;
- for (i = localCount*localRank; i < localCount*(localRank + ); i++, sign = -sign)
- sum += sign / ( * i + );
- printf("Thread %2d finished.\n", localRank);
- return nullptr;
- }
- int main()
- {
- pthread_t array[thread];
- int i;
- long long list[thread];
- clock_t time = clock();
- for (i = , sum = 0.0; i < thread; i++)
- {
- list[i] = i;
- pthread_create(&array[i], nullptr, threadSum_naïve, (void *)list[i]);
- }
- for (i = ; i < thread; i++)
- pthread_join(array[i], nullptr);
- time = clock() - time;
- printf("\nsum = %2.10f, time = %d ms\n", sum, time);
- getchar();
- return ;
- }
● 输出结果,发现与精确结果相差很大,这是由于读写冲突造成的
- Thread finished.
- Thread finished.
- Thread finished.
- Thread finished.
- Thread finished.
- Thread finished.
- Thread finished.
- Thread finished.
- sum = 0.7852892761, time = ms
● 忙等待法,代码
- #include <stdio.h>
- #include <pthread.h>
- #include <time.h>
- #pragma comment(lib, "pthreadVC2.lib")
- const int count = , thread = ;
- double sum;
- int flag;
- void* threadSum(void* rank)
- {
- const long long localRank = (long long)rank;
- const int localCount = count / thread;
- int i;
- double sign;
- if (localCount * localRank % )
- sign = -1.0;
- else
- sign = 1.0;
- for (i = localCount*localRank; i < localCount*(localRank + ); i++, sign = -sign)
- {
- while (flag != localRank); // 等待读写标志等于线程编号时进行写入
- sum += sign / ( * i + );
- flag = (flag + ) % thread;// 写入完成调整读写标志以便下一个线程写入
- }
- printf("Thread %2d finished.\n", localRank);
- return nullptr;
- }
- int main()
- {
- pthread_t array[thread];
- int i;
- long long list[thread];
- clock_t time = clock();
- flag = ;
- for (i = , sum = 0.0; i < thread; i++)
- {
- list[i] = i;
- pthread_create(&array[i], nullptr, threadSum, (void *)list[i]);
- }
- for (i = ; i < thread; i++)
- pthread_join(array[i], nullptr);
- time = clock() - time;
- printf("\nsum = %2.10f, time = %d ms\n", sum, time);
- getchar();
- return ;
- }
● 输出结果,发现花费的时间非常长,这是因为每个线程每次向结果中写入一个数,造成了极长的等待队列
- Thread finished.
- Thread finished.
- Thread finished.
- Thread finished.
- Thread finished.
- Thread finished.
- Thread finished.
- Thread finished.
- sum = 0.7853981632, time = ms
● 忙等待法 + 局部和,代码
- #include <stdio.h>
- #include <pthread.h>
- #include <time.h>
- #pragma comment(lib, "pthreadVC2.lib")
- const int count = , thread = ;
- double sum;
- int flag;
- void* threadSum(void* rank)
- {
- const long long localRank = (long long)rank;
- const int localCount = count / thread;
- int i;
- double sign, localSum;
- if (localCount * localRank % )
- sign = -1.0;
- else
- sign = 1.0;
- for (i = localCount * localRank, localSum = 0.0; i < localCount * (localRank + ); localSum += sign / ( * i + ), i++, sign = -sign);
- for (; flag != localRank;);// 仍然使用忙等待,但是每个线程仅向总和中写入一次部分和
- sum += localSum;
- flag = (flag + ) % thread;
- printf("Thread %2d finished.\n", localRank);
- return nullptr;
- }
- int main()
- {
- pthread_t array[thread];
- int i;
- long long list[thread];
- clock_t time = clock();
- flag = ;
- for (i = , sum = 0.0; i < thread; i++)
- {
- list[i] = i;
- pthread_create(&array[i], nullptr, threadSum, (void *)list[i]);
- }
- for (i = ; i < thread; i++)
- pthread_join(array[i], nullptr);
- time = clock() - time;
- printf("\nsum = %2.10f, time = %d ms\n", sum, time);
- getchar();
- return ;
- }
● 输出结果,速度大为加快
- Thread finished.
- Thread finished.
- Thread finished.
- Thread finished.
- Thread finished.
- Thread finished.
- Thread finished.
- Thread finished.
- sum = 0.7853981632, time = ms
● 使用互斥量,代码
- #include <stdio.h>
- #include <pthread.h>
- #include <time.h>
- #pragma comment(lib, "pthreadVC2.lib")
- const int count = , thread = ;
- double sum;
- pthread_mutex_t pmt;
- void* threadSum(void* rank)
- {
- const long long localRank = (long long)rank;
- const int localCount = count / thread;
- int i;
- double sign, localSum;
- if (localCount * localRank % )
- sign = -1.0;
- else
- sign = 1.0;
- for (i = localCount * localRank, localSum = 0.0; i < localCount * (localRank + ); localSum += sign / ( * i + ), i++, sign = -sign);
- pthread_mutex_lock(&pmt); // 与使用忙等待相同的办法使用互斥量
- sum += localSum;
- pthread_mutex_unlock(&pmt);
- printf("Thread %2d finished.\n", localRank);
- return nullptr;
- }
- int main()
- {
- pthread_t array[thread];
- int i;
- long long list[thread];
- clock_t time = clock();
- pthread_mutex_init(&pmt, nullptr);// 初始化互斥量
- for (i = , sum = 0.0; i < thread; i++)
- {
- list[i] = i;
- pthread_create(&array[i], nullptr, threadSum, (void *)list[i]);
- }
- for (i = ; i < thread; i++)
- pthread_join(array[i], nullptr);
- pthread_mutex_destroy(&pmt); // 销毁互斥量
- time = clock() - time;
- printf("\nsum = %2.10f, time = %d ms\n", sum, time);
- getchar();
- return ;
- }
● 输出结果,速度与使用忙等待相近
- Thread finished.
- Thread finished.
- Thread finished.
- Thread finished.
- Thread finished.
- Thread finished.
- Thread finished.
- Thread finished.
- sum = 0.7853981632, time = ms
● 用到的定义,pthread.h
- typedef struct pthread_mutex_t_ * pthread_mutex_t;
- typedef struct pthread_mutexattr_t_ * pthread_mutexattr_t;
- PTW32_DLLPORT int PTW32_CDECL pthread_mutex_init(pthread_mutex_t * mutex, const pthread_mutexattr_t * attr);
- // 初始化互斥量,输入已经声明的一个 pthread_mutex_t 变量的指针及一个 pthread_mutexattr_t 属性指针,初始化完成后互斥量为解锁状态
- PTW32_DLLPORT int PTW32_CDECL pthread_mutex_destroy(pthread_mutex_t * mutex); // 销毁用完的互斥量
- PTW32_DLLPORT int PTW32_CDECL pthread_mutex_lock(pthread_mutex_t * mutex); // 锁定互斥量以访问临界区
- PTW32_DLLPORT int PTW32_CDECL pthread_mutex_unlock(pthread_mutex_t * mutex); // 解锁互斥量以离开临界区访问
Pthreads Hello World,忙等待,互斥量的更多相关文章
- 【转】【Linux】 临界区,互斥量,信号量,事件的区别
原文地址:http://blog.itpub.net/10697500/viewspace-612045/ Linux中 四种进程或线程同步互斥的控制方法1.临界区:通过对多线程的串行化来访问公共资源 ...
- 经典线程同步 互斥量Mutex
阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇一个经典的多线程同步问题> <秒杀多线程第五篇经典线程同步关键段CS> <秒杀多线程第六篇经典线程同步事件Event& ...
- Linux的线程同步对象:互斥量Mutex,读写锁,条件变量
进程是Linux资源分配的对象,Linux会为进程分配虚拟内存(4G)和文件句柄等 资源,是一个静态的概念.线程是CPU调度的对象,是一个动态的概念.一个进程之中至少包含有一个或者多个线程.这 ...
- [一个经典的多线程同步问题]解决方案三:互斥量Mutex
本篇通过互斥量来解决线程的同步,学习其中的一些知识. 互斥量也是一个内核对象,它用来确保一个线程独占一个资源的访问.互斥量与关键段的行为非常相似,并且互斥量可以用于不同进程中的线程互斥访问资源.使用互 ...
- (转)经典线程同步 互斥量Mutex
阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇一个经典的多线程同步问题> <秒杀多线程第五篇经典线程同步关键段CS> <秒杀多线程第六篇经典线程同步事件Event& ...
- 多线程面试题系列(7):经典线程同步 互斥量Mutex
前面介绍了关键段CS.事件Event在经典线程同步问题中的使用.本篇介绍用互斥量Mutex来解决这个问题. 互斥量也是一个内核对象,它用来确保一个线程独占一个资源的访问.互斥量与关键段的行为非常相似, ...
- windows多线程同步--互斥量
关于互斥量的基本概念:百度百科互斥量 推荐参考博客:秒杀多线程第七篇 经典线程同步 互斥量Mutex 注意:互斥量也是一个内核对象,它用来确保一个线程独占一个资源的访问.互斥量与关键段的行为非常相似, ...
- 秒杀多线程第七篇 经典线程同步 互斥量Mutex
本文转载于:http://blog.csdn.net/morewindows/article/details/7470936 前面介绍了关键段CS.事件Event在经典线程同步问题中的使用.本篇介绍用 ...
- windows多线程(六) 互斥量Mutex与关键段CriticalSection比较
一.关键段CS 和 互斥量Mutex 的相同点:都有线程拥有权 关键段和互斥量都有线程拥有权,即可以被一个线程拥有.在 前面讲关键段CS的文章中有说到,关键段结构体的第四个参数保存着拥有该关键段的线程 ...
- windows多线程(五) 互斥量 Mutex
一.互斥量 互斥量是windows的一个内核对象,互斥量与关键段的作用相似,可以用来确保全局资源的互斥访问.并且互斥量可以用在不同的进程中的线程互斥访问全局资源. 二.相关函数说明 使用互斥量Mute ...
随机推荐
- 安装 android x86 到 virtual box
由于vmware无论怎么整,声音都出不了. 改用virtual box了. 很多注意点都参照了这篇文章 http://www.android-x86.org/documents/virtualboxh ...
- ContentNegotiatingViewResolver多种输出格式实例: json/jsp/xml/xls/pdf
ContentNegotiatingViewResolver多种输出格式实例: json/jsp/xml/xls/pdf 本例用的是javaConfig配置 以pizza为例. json输出需要用到的 ...
- 无边框WPF窗体——允许拖动
https://blog.csdn.net/zjcxhswill/article/details/38646525
- 《BAT前端进阶[师徒班]》学习总结
这是一个培训课 是的,这是一个面向中级前端的培训班,但明显跟传统的填鸭式培训班不太一样.这边的老师都是大牛这是毫无疑问的,而且都是一线开发人员.而且课程一开始就说明了面向了是有1-3年有工作经验的前端 ...
- 编译安装zabbix3.2.5
1. 配置lnmp环境 首先配置Nginx+mysql+php-fpm的系统环境,具体配置见另一篇文章 2. 编译安装zabbix 2.1 下载并解压zabbix 可以到zabbix官网下载zabbi ...
- Struts2基本使用(三)--数据交互
Struts2中的数据交互 在Struts2中我们不必再使用request.getParameter()这种方式来获取前台发送到服务器的参数. 我们可以在服务器端的Java类中直接声明一个和前台发送数 ...
- 201621123006 《Java程序设计》第10周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常相关内容. 2. 书面作业 本次PTA作业题集异常 1. 常用异常 结合题集题目7-1回答 1.1 自己以前编写的代码中经常出现 ...
- java基础11天
冒泡排序 相邻元素两两比较,大的往后放,第一次完毕,最大值出现在了最大索引处,第二次比较厚,最大值放在了倒数第二的位置,一直到第二个元素确定了,整个数组的顺序也就确定了 public class Ar ...
- New Concept English Two 10 25
$课文23 新居 219. I had a letter from my sister yesterday. 昨天我收到了姐姐的一封信, 220. She lives in Nigeria. 她住在尼 ...
- Python 使用Microsoft SQL Server数据库
软件环境: Windows 7 32bit Python 3.6 Download https://www.python.org/downloads/ 默认安装,并添加环境变量,一路Next ... ...