zoukankan      html  css  js  c++  java
  • linux高编线程-------线程同步-互斥量

    线程同步

    互斥量:某一个资源可能在使用的过程中产生竞争和冲突。那么互斥量解决同一时刻只有线程对资源进行操作。限制的是代码。

    /**********************
     *功能:销毁一个互斥量
     *参数:mutex:类型为pthread_mutex_t类型的变量
     *返回值:成功返回0,失败返回errno
     * *******************/
    int pthread_mutex_destroy(pthread_mutex_t *mutex);
    
    /********************
     *功能:动态创建互斥量:如果 变量位于一个结构体中,用动态初始化
     *参数:mutex:互斥变量
     *      attr:属性
     * *****************/
    int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);
    
    /******************
     *静态初始化
     *互斥量如果是一个变量的话可以用静态初始化
     * **************/
    pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
    
    /****lock-unlock:创建一个临界区****/
    /****lock:是非阻塞,lock是阻塞*****/
    int pthread_mutex_lock(pthread_mutex_t *mutex);
    int pthread_mutex_trylock(pthread_mutex_t *mutex);
    int pthread_mutex_unlock(pthread_mutex_t *mutex);
    /*****************
     *功能:保证线程只被执行一次
     *参数:once_control:变量
     *      init_routine:线程函数入口地址
     ****************/
    int pthread_once(pthread_once_t *once_control,void (*init_routine)(void));
    pthread_once_t once_control = PTHREAD_ONCE_INIT;

    下面两个例子说明线程互斥的使用

    /*********
    功能:创建20个线程,每个线程的任务就是从文件中读取数据,加1后,写入文件
    使用到的相关知识:线程的创建销毁以及线程的互斥(解决线程之间的进程问题)
    *********/
    #include <stdio.h>
    #include <stdlib.h>
    #include <pthread.h>
    
    #define THRNUM        20    
    #define FNAME        "/tmp/out"
    #define SIZE        1024
    //创建互斥量
    static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
    //线程
    static void *thr_add(void *p)
    {
        FILE *fp;
        char buf[SIZE];
        //1.打开文件
        fp = fopen(FNAME,"r+");    
        if(fp == NULL)
        {
            perror("fopen()");
            exit(1);
        }
        //2.锁住将要执行的代码
        pthread_mutex_lock(&mut);
        
        fgets(buf,SIZE,fp);
        rewind(fp);
    //    sleep(1);
        fprintf(fp,"%d
    ",atoi(buf)+1);
        fclose(fp);
        //3.解锁
        pthread_mutex_unlock(&mut);
        //4.线程退出
        pthread_exit(NULL);
    }
    
    int main()
    {
        int i,err;    
        //1.创建THRNUM个线程
        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
    ",strerror(err));
                exit(1);
            }
        }
        //2.等待收尸
        for(i = 0; i < THRNUM ;i++)
            pthread_join(tid[i],NULL);
        //3.销毁互斥量
        pthread_mutex_destroy(&mut);
    
        exit(0);
    }

    范例2:四个线程不断向终端输出abcd字符,用线程a解线程b的锁,b解c的锁依次类推

    /*******************
    功能:4个线程分别向终端按照次序输出abcd
    使用的知识:线程互斥量
    ********************/
    #include <stdio.h>
    #include <stdlib.h>
    #include <pthread.h>
    
    #define THRNUM        4    
    //四个线程的线程互斥量
    static pthread_mutex_t mut[THRNUM];
    
    /*函数功能:返回下一个线程顺序*/
    static int next(int a)
    {
        if(a+1 == THRNUM)
            return 0;
        return a+1;
    }
    //线程
    static void *thr_func(void *p)
    {
        int n = (int)p;
        int ch = 'a' + n;
    
        while(1)
        {
            //1.锁住当前线程执行代码
            pthread_mutex_lock(mut+n);
            write(1,&ch,1);
            //2.解锁下一个线程执行代码
            pthread_mutex_unlock(mut+next(n));
        }
        //3.线程退出
        pthread_exit(NULL);
    }
    
    int main()
    {
        int i,err;    
        pthread_t tid[THRNUM];
        //1.创建线程并创建互斥量
        for(i = 0; i < THRNUM ;i++)
        {
            pthread_mutex_init(mut+i,NULL);
            pthread_mutex_lock(mut+i);
    
            err = pthread_create(tid+i,NULL,thr_func,(void *)i);
            if(err)
            {
                fprintf(stderr,"pthread_create():%s
    ",strerror(err));
                exit(1);
            }
        }
        //2.解锁第一个线程互斥量
        pthread_mutex_unlock(mut+0);
        //3.5s信号打断
        alarm(5);
        
        //4.收尸
        for(i = 0; i < THRNUM ;i++)
        {
            pthread_join(tid[i],NULL);
        }
        exit(0);

     筛质数:

    /******************
     *功能:多线程筛质数
     *知识点:互斥锁的使用
     * **************/
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <pthread.h>
    #include <unistd.h>
    //质数范围
    #define LEFT        30000000
    #define RIGHT       30000200
    //线程数量
    #define THRNUM      4
    
    //num > 0 有任务
    //num = 0 无任务
    //num = -1 完成
    static int num = 0 ;
    //互斥量
    static pthread_mutex_t mut_num = PTHREAD_MUTEX_INITIALIZER ;
    
    void *thr_primer(void *);
    
    int main()
    {
        int i,err;
        pthread_t tid[THRNUM];
        //1.创建THRNUM个线程
        for(i = 0; i <= THRNUM ;i++)
        {
            err = pthread_create(tid+(i),NULL,thr_primer,(void *)i);
            if(err)
            {
                fprintf(stderr,"pthread_create():%s
    ",strerror(err));
                exit(1);
            }
        }
        //2.main线程负责下发任务
        //  每次查看num的值之前需要加锁
        for(i = LEFT ; i <= RIGHT ; i++)
        {
            //2.1看num的值,需要加锁
            pthread_mutex_lock(&mut_num);
            //2.2:num != 0 :说明任务还没有派发下去
            while(num != 0)
            {
                //2.2.1等待,让线程有机会把数拿走
                pthread_mutex_unlock(&mut_num);
                // 2.2.2出让调度器给别的线程
                sched_yield();
                //2.2.3其他线程抢锁后加锁+解锁,main线程需要抢锁继续下发任务
                pthread_mutex_lock(&mut_num);
            }
            //2.3下发任务
            num = i ;
            //2.4解锁
            pthread_mutex_unlock(&mut_num);
    
        }
        //3.所有任务处理完毕:需要查看num值是否为0,所以加锁查看
        pthread_mutex_lock(&mut_num);
        //3.1最后一个任务发出去后,但是其他线程没有处理完,main线程又抢到锁
        while(num != 0)
        {
            //解锁
            pthread_mutex_unlock(&mut_num);
            //出让调度器
            sched_yield();
            //抢锁
            pthread_mutex_lock(&mut_num);
        }
        //4.所有任务处理完毕,解锁
        num = -1 ;
        pthread_mutex_unlock(&mut_num);
        //5.收尸
        for(i = LEFT; i <= THRNUM ;i++)
            pthread_join(tid[i],NULL);
        //6.销毁互斥量
        pthread_mutex_destroy(&mut_num);
        exit(0);
    
    }
    
    //线程:需要注意临界区的跳转一定要解锁
    void *thr_primer(void *p)
    {
        int i,j,mark;
        while(1)
        {
            //加锁看num的值
            pthread_mutex_lock(&mut_num);
            //num = 0 解锁等待不为0 的时候
            while(num == 0)
            {
                //为0 解锁等待
                pthread_mutex_unlock(&mut_num);
                sched_yield();
                //再抢锁看num的值
                pthread_mutex_lock(&mut_num);
            }
            if(num == -1)
            {
                //没有任务的时候解锁并跳出循环
                pthread_mutex_unlock(&mut_num);
                break ;
            }
            i = num ;
            num = 0 ;
            pthread_mutex_unlock(&mut_num);
    
            mark = 1;
            for(j = 2; j < i/2; j++)
            {
                if(i % j == 0)
                {
                    mark = 0;
                    break;
                }
            }
            if(mark)
                printf("[%d]%d is a primer.
    ",(int)p,i);
        }
        pthread_exit(NULL);
    }
  • 相关阅读:
    Java实现 LeetCode 32 最长有效括号
    Java实现 LeetCode 31下一个排列
    Java实现 LeetCode 31下一个排列
    Java实现 LeetCode 31下一个排列
    Java实现 蓝桥杯 素因子去重
    Java实现 蓝桥杯 素因子去重
    Java实现 蓝桥杯 素因子去重
    Java实现 LeetCode 30 串联所有单词的子串
    Visual c++例子,可不使用常规的对话框资源模板的情况下,动态创建对话框的方法
    MFC不使用对话框资源模版创建对话框
  • 原文地址:https://www.cnblogs.com/muzihuan/p/5353225.html
Copyright © 2011-2022 走看看