学习pthreads,使用互斥量进行同步

7 篇文章 0 订阅
7 篇文章 5 订阅

在进行多线程编程时,我们总会遇到全局变量和数据结构的问题,这是多线程之间进行通信的问题。如果多个线程同时读写一个全局变量,那么会造成竞争或者出错。为了解决这一问题,我们需要对全局数据进行,使用互斥量实现锁的机制,当某个线程在某个操作前进行了加锁,那么某个操作只能在这个线程进行,直至将锁去除,相当于在这里将多线程的并行变成了串行。本文重点学习如何使用互斥量进行全局数据的同步,分为三个部分,第一部分给出代码示例,第二部分对代码进行讲解,第三部分给出运行结果。

一、代码示例

该程序使用4个线程实现两个向量的点积运算。

#include "StdAfx.h"
#include 
   
   
    
    
#include 
    
    
     
     
#include 
     
     
      
      

typedef struct 
 {
   double      *a;
   double      *b;
   double     sum; 
   int     veclen; 
 } DOTDATA;


#define NUMTHRDS 4
#define VECLEN 100000
   DOTDATA dotstr; 
   pthread_t callThd[NUMTHRDS];
   pthread_mutex_t mutexsum;


void *dotprod(void *arg)
{
   int i, start, end, len ;
   long offset;
   double mysum, *x, *y;
   offset = (long)arg;
     
   len = dotstr.veclen;
   start = offset*len;
   end   = start + len;
   x = dotstr.a;
   y = dotstr.b;

   mysum = 0;
   for (i=start; i
      
      
     
     
    
    
   
   

二、代码讲解

typedef struct 
 {
   double      *a;
   double      *b;
   double     sum; 
   int     veclen; 
 } DOTDATA;

定义DOTDATA结构体,里面包含4个成员变量,可表示两个向量,乘积和向量的长度。

#define NUMTHRDS 4
#define VECLEN 100000
   DOTDATA dotstr; 
   pthread_t callThd[NUMTHRDS];
   pthread_mutex_t mutexsum;

定义全局变量和互斥量

   int i, start, end, len ;
   long offset;
   double mysum, *x, *y;
   offset = (long)arg;
     
   len = dotstr.veclen;
   start = offset*len;
   end   = start + len;
   x = dotstr.a;
   y = dotstr.b;

为了点积运算的方便,定义和使用一些局部变量

   mysum = 0;
   for (i=start; i
    
    

计算点积

   pthread_mutex_lock (&mutexsum);
   dotstr.sum += mysum;
   printf("Thread %ld did %d to %d:  mysum=%f global sum=%f\n",offset,start,end,mysum,dotstr.sum);
   pthread_mutex_unlock (&mutexsum);

   pthread_exit((void*) 0);
   return(NULL);

给互斥量加锁,更新全局变量结构体中的数据,更新完成解锁,然后退出线程

a = (double*) malloc (NUMTHRDS*VECLEN*sizeof(double));
b = (double*) malloc (NUMTHRDS*VECLEN*sizeof(double));
  
for (i=0; i
     
     

给两个向量分配内存空间并赋值,然后给全局变量结构体中数据赋值,最后初始化互斥量

pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

for(i=0;i
      
      

初始化所要执行的线程属性对象,并将其设置为可结合的,然后根据属性对象创建4个线程,执行 dotprod程序,并传递线程的ID

pthread_attr_destroy(&attr);

for(i=0;i
       
       

删除属性对象,然后结合线程,知道每个线程都结束才执行下一步程序

printf ("Sum =  %f \n", dotstr.sum);
free (a);
free (b);
pthread_mutex_destroy(&mutexsum);
pthread_exit(NULL);

打印输出点积结果 ,释放两个向量的内存,删除互斥量,退出线程。

三、运行结果

### 回答1: 这个现象说明了使用互斥会导致线程之间的竞争,从而降低程序的性能。当线程数大于可用的 CPU 数时,线程调度器会将线程在不同的 CPU 上进行调度,从而提高程序的并行度和性能。因此,应该尽可能地避免使用互斥,采用更高效的同步机制,如信号、条件变等,来避免线程之间的竞争,并且合理地调度线程,以充分利用可用的处理器资源。此外,还可以采用一些优化技术,如线程绑定、局部性优化等,来进一步提高程序的性能。 ### 回答2: 如果增加线程的个数,直至超过可使用的CPU数,我们发现使用互斥的计算程序的性能几乎保持不变。这个现象说明应该如何在可用的处理器上调度线程呢? 这个现象表明,增加线程数并不会提高程序的性能。这是因为当线程数超过可用的CPU数时,多余的线程会需要等待CPU时间片的分配。在使用互斥的计算程序中,互斥会使得多个线程只能依次执行,而不能同时执行。因此,即使有更多的线程可以同时运行,但由于互斥的限制,他们只能依次执行,导致整体性能保持不变。 针对这个现象,在可用的处理器上调度线程时,可以考虑以下策略: 1.合理控制线程数:根据CPU的数和性能,合理确定线程的数,避免创建过多的线程导致性能下降。 2.充分利用多核处理器:如果可用的处理器是多核的,可以采用并行执行的方式,将任务分配给多个核心同时执行,从而提高性能。 3.避免不必要的线程同步:减少对互斥使用次数,尽避免不必要的线程同步操作,减少线程之间的竞争,提高并发性能。 4.任务划分和负载均衡:合理划分任务和负载,确保每个线程都有足够的工作,并尽均匀地分配到各个处理器上,避免出现负载不均衡的情况,提高整体性能。 通过以上调度策略,可以更好地利用可用的处理器资源,提高线程的运行效率和整体性能。 ### 回答3: 当增加线程的个数,直至超过可使用的CPU数目时,使用互斥的r计算程序的性能几乎保持不变。这个现象说明在可用的处理器上调度线程时,需要考虑以下几点: 首先,合理分配线程与CPU之间的对应关系。如果线程的数超过了可用的CPU数目,那么多个线程可能会同时竞争同一个CPU资源,导致资源浪费和线程等待。因此,需要根据系统的CPU数合理分配线程,避免过多线程相互竞争。 其次,根据程序的特点和任务的类型设置合适的线程优先级。不同的任务可能对性能有不同的要求,某些任务可能更加重要,需要更高的优先级来保证其执行效率。通过设置合适的线程优先级,可以确保在可用的处理器上充分利用线程的计算能力。 此外,需要考虑线程间的通信和同步机制。使用互斥是一种常见的同步机制,但在高并发环境中可能会引发竞争条件。在设计线程调度策略时,可以考虑采用其他更高效的同步机制,如读写锁、条件变等,以减少线程竞争和等待的情况,提高程序的执行效率。 最后,通过合理的负载均衡算法将任务分配给CPU。由于不同的线程可能对处理器产生不同的负载,因此需要考虑将任务均匀地分布在可用的处理器上,以实现更好的线程调度效果。可以根据任务的复杂度、计算等因素来进行负载均衡,确保每个处理器都能得到合理的利用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值