线程------竞争,互斥量---多线程对同一文件读写问题

当多个控制线程共享相同的内存时呢,需要确保每个线程看到一致的数据视图。

如果每个线程使用的变量都是其他线程不会读取和修改,那么就不存在一致性的问题。

线程互斥接口用来保护数据,用于确保同一时间只有一个线程访问数据。

互斥:限制代码---独占

很久以前:

下面程序存在竞争问题的哟,当创建20个线程,每个线程都对同一个文件进行读写操作,有可能发生N个线程同时对文件进行打开和读操作,在写的过程可能会对同一个数重复进行+1操作。比如说读到  1, 然后N个线程取到1 并对1这个数做+1操作。

/*
    实现20个线程分别向/tmp/out写+1操作
    问题:运行结果应该为21,对于多核设备,运行会存在竞争,运行结果不确定
    (多个线程打开文件)
*/
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#define THRNUM      20  //线程数量
#define MAXLINE     1024//从文件读最大字节数
#define FILENAME    "/tmp/out"
void * thr_add(void *p)
{
    FILE * fp;
    char linebuf[MAXLINE];
    //open
   fp = fopen(FILENAME , "r+");
   if(fp == NULL )
   {
        perror("fopen()");
        exit(1);
   }
    //read
    fgets(linebuf,MAXLINE,fp);
    //write
    rewind(fp);//文件偏移量设备文件开始位置
    fprintf(fp,"%d\n",atoi(linebuf)+1);
    //close
    fclose(fp);
    pthread_exit(NULL);
}

int main()
{

    int i , err;
    pthread_t tid[THRNUM];
    //创建线程
    for(i = 0 ; i < THRNUM ; i++)
    {
        err = pthread_create(tid+i,NULL,thr_add,NULL);
        if(err)
        {
            fprintf(stderr , "pthread_create():%s\n",strerror(err));
            exit(1);
        }
    }
    //收尸
    for(i = 0 ; i < THRNUM ; i++)
    {
        pthread_join(tid[i],NULL);
    }   

解决办法:就是互斥咯

互斥创建

       int pthread_mutex_destroy(pthread_mutex_t *mutex);//互斥量销毁
       int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);//动态初始化:参数1:变量;参数2:属性;
       pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;//静态初始化

加锁和解锁:

       int pthread_mutex_lock(pthread_mutex_t *mutex);//阻塞
       int pthread_mutex_trylock(pthread_mutex_t *mutex);//
       int pthread_mutex_unlock(pthread_mutex_t *mutex);//解锁

so,程序修改为:给他加上锁

#include <pthread.h>
#include <string.h>
#define THRNUM      20  //线程数量
#define MAXLINE     1024//从文件读最大字节数
#define FILENAME    "/tmp/out"

static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;//定义个锁

void * thr_add(void *p)
{
    FILE * fp;
    char linebuf[MAXLINE];
    //open
   fp = fopen(FILENAME , "r+");
   if(fp == NULL )
   {
        perror("fopen()");
        exit(1);
   }
    pthread_mutex_lock(&mut);
    //read
    fgets(linebuf,MAXLINE,fp);
    //write
    rewind(fp);//文件偏移量设备文件开始位置
    fprintf(fp,"%d\n",atoi(linebuf)+1);
    //close
    fclose(fp);
    pthread_mutex_unlock(&mut);
    pthread_exit(NULL);
}

int main()
{

    int i , err;
    pthread_t tid[THRNUM];
    //创建线程
    for(i = 0 ; i < THRNUM ; i++)
    {
        err = pthread_create(tid+i,NULL,thr_add,NULL);
        if(err)
        {
            fprintf(stderr , "pthread_create():%s\n",strerror(err));
            exit(1);
        }
    }
    //收尸
    for(i = 0 ; i < THRNUM ; i++)
    {
        pthread_join(tid[i],NULL);
    }
    pthread_mutex_destroy(&mut);// 销毁互斥
    exit(0);
}

ok!

时间: 2025-01-16 03:47:47

线程------竞争,互斥量---多线程对同一文件读写问题的相关文章

转--- 秒杀多线程第七篇 经典线程同步 互斥量Mutex

阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇一个经典的多线程同步问题> <秒杀多线程第五篇经典线程同步关键段CS> <秒杀多线程第六篇经典线程同步事件Event> 前面介绍了关键段CS.事件Event在经典线程同步问题中的使用.本篇介绍用互斥量Mutex来解决这个问题. 互斥量也是一个内核对象,它用来确保一个线程独占一个资源的访问.互斥量与关键段的行为非常相似,并且互斥量可以用于不同进程中的线程互斥访问资源.使用互斥量Mutex主要将用到四个函数.下面是这些函数

秒杀多线程第七篇 经典线程同步 互斥量Mutex

阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇一个经典的多线程同步问题> <秒杀多线程第五篇经典线程同步关键段CS> <秒杀多线程第六篇经典线程同步事件Event> 前面介绍了关键段CS.事件Event在经典线程同步问题中的使用.本篇介绍用互斥量Mutex来解决这个问题. 互斥量也是一个内核对象,它用来确保一个线程独占一个资源的访问.互斥量与关键段的行为非常相似,并且互斥量可以用于不同进程中的线程互斥访问资源.使用互斥量Mutex主要将用到四个函数.下面是这些函数

c++11 线程的互斥量

c++11 线程的互斥量 为什么需要互斥量 在多任务操作系统中,同时运行的多个任务可能都需要使用同一种资源.这个过程有点类似于,公司部门里,我在使用着打印机打印东西的同时(还没有打印完),别人刚好也在此刻使用打印机打印东西,如果不做任何处理的话,打印出来的东西肯定是错乱的. #define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <string> #include <chrono> #include &l

线程同步——互斥量

同步的概念 多个线程可以共享内存空间,在程序中不可避免的需要多个线程协作完成某个功能.那么这些线程就可能会使用某个公共的资源.比如说全局变量,某个文件等等.为了不产生冲突,冲突会产生在多个线程的写操作之间,而读操作则很安全.这就需要多个线程之间的同步. 互斥量的原理 互斥量 实现同步的机制很好理解.可以将互斥量想象为锁.只有当一个线程获得该锁时才有权限对共享资源的操作.从而可以理解为该线程对共享资源上了一把锁,其他线程无权操作.在此线程操作完成之后,需要解锁以便其他线程可以获得该锁.可以想的出来

(转)经典线程同步 互斥量Mutex

阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇一个经典的多线程同步问题> <秒杀多线程第五篇经典线程同步关键段CS> <秒杀多线程第六篇经典线程同步事件Event> 前面介绍了关键段CS.事件Event在经典线程同步问题中的使用.本篇介绍用互斥量Mutex来解决这个问题. 互斥量也是一个内核对象,它用来确保一个线程独占一个资源的访问.互斥量与关键段的行为非常相似,并且互斥量可以用于不同进程中的线程互斥访问资源.使用互斥量Mutex主要将用到四个函数.下面是这些函数

pThread线程(二) 线程同步--互斥量/锁

互斥量(Mutex)是“mutual exclusion”的缩写.互斥量是实现线程同步,和保护同时写共享数据的主要方法. 互斥量对共享数据的保护就像一把锁.在Pthreads中,任何时候仅有一个线程可以锁定互斥量,因此,当多个线程尝试去锁定该互斥量时仅有一个会成功.直到锁定互斥量的线程解锁互斥量后,其他线程才可以去锁定互斥量.线程必须轮着访问受保护数据. 一个拥有互斥量的线程经常用于更新全局变量.确保了多个线程更新同样的变量以安全的方式运行,最终的结果和一个线程处理的结果是相同的.这个更新的变量

linux系统编程:线程同步-互斥量(mutex)

线程同步-互斥量(mutex) 线程同步 多个线程同时访问共享数据时可能会冲突,于是需要实现线程同步. 一个线程冲突的示例 #include <stdio.h> #include <unistd.h> #include <pthread.h> #define Loop 1000000 //全局资然 int counter = 0; void *fun(void *argv) { int i; for (i = 0; i < Loop; i++) { counter

生产者-消费者问题:介绍POSIX线程的互斥量和条件变量的使用

全局初始化互斥量和条件变量(不全局也行,但至少要对线程启动函数可见,这样才能使用.) static pthread_cont_t cond = PTHREAD_COND_INITIALIZER; static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; 使用互斥量锁住一块代码方法如下(默认忽略pthread开头的函数的错误检查,即类似 int s = pthread_xxx(...); if (s != 0) { printErrorMsg(

线程同步---互斥量mutex

1. 问题引入:开两个线程同时对一个全局变量10万次做自加,结果会如何? #include <stdio.h> #include <string.h> #include <pthread.h> unsigned int g_cn = 0; void* thread_proc (void* arg) { unsigned int i; for (i = 0; i < 100000; i++) ++g_cn; return NULL; } int main (void