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\n",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\n",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\n",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\n",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.\n",(int)p,i);
    }
    pthread_exit(NULL);
}

 

posted @ 2016-04-05 10:35  muzihuan  阅读(325)  评论(0编辑  收藏  举报