分享

多线程加锁

 mrjbydd 2012-08-24

Linux pthread_mutex演示程序

Linux pthread 中使用mutex 进行互斥的程序和结果

#include "stdio.h"
#include "string.h"
#include "stdlib.h"
#include "pthread.h"


#define THREAD_NUMBER 2

int sum = 0;

void* fun(void* arg) {
    int t = (*(int*)arg);
    int i;
    for (i = t ;i < 10000; i += 2)
         sum = sum + i;
    return NULL;
}

int main(){
     pthread_t T[THREAD_NUMBER];
    int arg[THREAD_NUMBER];
    int ret,i;
    void* join_result;
    
    for (i =0 ;i < THREAD_NUMBER; ++ i){
         arg[i] = i;
         ret = pthread_create(&T[i],NULL,fun,(void*)&arg[i]);
        if (ret){
             printf("Thread %d crreate failure!\n",i);
             exit(EXIT_FAILURE);
         }
     }
    for (i = 0 ;i < THREAD_NUMBER; ++ i){
         ret = pthread_join(T[i],&join_result);
        if (ret) {
             printf("Thread %d join failure!\n",i);
             exit(EXIT_FAILURE);
         }
     }
     printf("sum = %d\n",sum);
    return 0;
}

上面的程序是没有进行互斥的 nomutex.c 该程序用于求 1...9999的和,可以gcc -l pthreacd -o test nomutex.c编译该程序,
并且可以实验运行结果基本上都是不对的,由于该程序没有应用互斥操作,所以可想而知为什么结果是不对的。

下面的程序就在上面程序的基础上加上了求和时的互斥操作,所以运行结果都是对的。
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
#include "pthread.h"


#define THREAD_NUMBER 2

int sum = 0;

static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void* fun(void* arg) {
    int t = (*(int*)arg);
    int i;
    for (i = t ;i < 10000; i += 2) {
         pthread_mutex_lock(&mutex);
         sum = sum + i;
         pthread_mutex_unlock(&mutex);
     }
    return NULL;
}

int main(){
     pthread_t T[THREAD_NUMBER];
    int arg[THREAD_NUMBER];
    int ret,i;
    void* join_result;
    
    for (i =0 ;i < THREAD_NUMBER; ++ i){
         arg[i] = i;
         ret = pthread_create(&T[i],NULL,fun,(void*)&arg[i]);
        if (ret){
             printf("Thread %d crreate failure!\n",i);
             exit(EXIT_FAILURE);
         }
     }
    for (i = 0 ;i < THREAD_NUMBER; ++ i){
         ret = pthread_join(T[i],&join_result);
        if (ret) {
             printf("Thread %d join failure!\n",i);
             exit(EXIT_FAILURE);
         }
     }
     printf("sum = %d\n",sum);
    return 0;
}
用这两个小程序,只是想演示一下linuxpthread 的互斥操作。可以看到,在多线程环境中,为了保证共享变量的值的正确性,
互斥是非常重要的。



我觉得应该加锁。理由如下:
     比如说有多个线程都要读一个文件。
     先要open 打开一个文件,得到一个fd

对任一个读线程来说操作如下:
     1. lseek(fd..)到适当的位置
     2. read(fd..)

虽然以上每一个都是原子操作,可是1,2之间是可以中断的。如果线程一lseek了之后,系统暂时挂起线程1,运行线程二,线程也调用lseek。

内核给每一个进程有一个进程描述结构,在Linux中task_struct,在FreeBSD中是proc,存放每一个进程的信息。(下面以FreeBSD为例,因为linux不太清楚,原理应该是一样的).
proc里有一个struct filedesc,这里存放一个进程所有打开的文件的信息。它里面有一个struct file的表,每一个表表示这个进程一个打开文件。struct file里面记录了调用lseek设定的这个文件offset大小,对这个文件的读写都是从这里开始的。也就是说这个offset实际上是进程的各个线程共享的。
如果出现像上面说的那种情况,线程一设定的offset就被线程二给修改了。当线程一再开始运行的时候,读到的数据肯定是错误的。

所以说,为了数据的正确性,多线程读一个文件也应该加锁。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多