互斥

简单地理解就是,一个线程进入工作区后,如果有其他线程想要进入工作区,它就会进入等待状态,要等待工作区内的线程结束后才可以进入。

基本函数

(1)  pthread_mutex_init函数

原型:int pthread_mutex_init ( pthread_mutex_t *mutex,  const pthread_mutexattr_t* attr);

描述:设置互斥量的属性

参数:第一个参数:预先声明的pthread_mutex_t对象指针

第二个参数:互斥锁属性,NULL表示使用默认属性

返回值:成功时返回0, 失败时返回一个错误代码

(2) pthread_mutex_lock函数

原型:int pthread_mutex_lock ( pthread_mutex_t *mutex );

描述:pthread_mutex_lock返回时,互斥锁被锁定,如果这个互斥锁被一个线程锁定和拥有,那么另一个线程要调用这        个函数会进入堵塞状态(即等待状态),直到互斥锁被释放为止。

返回值:成功时返回0, 失败时返回一个错误代码

(3) pthread_mutex_unlock函数

原型:int pthread_mutex_unlock ( pthread_mutex_t *mutex );

描述:释放互斥锁

返回值:成功时返回0, 失败时返回一个错误代码

(4) pthread_mutex_destroy函数

原型:int pthread_mutex_destroy ( pthread_mutex_t *mutex );

描述:删除互斥锁

返回值:成功时返回0, 失败时返回一个错误代码

实例

lock.c文件

描述:这个程序主要可以概括为主线程负责接受输入的字符串,而子线程则负责统计并输出字符数。

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
void *thread_function(void *arg);
pthread_mutex_t work_mutex;  
#define WORK_SIZE 1024
char work_area[WORK_SIZE];
int time_to_exit = 0;
int main() {
    int res;
    pthread_t a_thread;
    void *thread_result;
    /*初始化互斥量*/
    res = pthread_mutex_init(&work_mutex, NULL);
    if (res != 0) {
        perror("互斥量初始化失败!");
        exit(EXIT_FAILURE);
    }
    /*启动新线程*/
    res = pthread_create(&a_thread, NULL, thread_function, NULL);
    if (res != 0) {
        perror("线程创建失败");
        exit(EXIT_FAILURE);
    }
    pthread_mutex_lock(&work_mutex);
    printf("请输入一些文本内容. 输入“end”结束\n");
    while(!time_to_exit) {
        fgets(work_area, WORK_SIZE, stdin);
        pthread_mutex_unlock(&work_mutex);
        while(1) {
            pthread_mutex_lock(&work_mutex);
            /*统计字符工作未完成*/
            if (work_area[0] != '\0') {
                pthread_mutex_unlock(&work_mutex);
                sleep(1);
            }
            else {
                /*统计字符工作完成,跳出内层循环,重新读取输入*/
                break;
            }
        }
    }
    pthread_mutex_unlock(&work_mutex);
    printf("\n等待线程结束...\n");
    res = pthread_join(a_thread, &thread_result);
    if (res != 0) {
        perror("Thread join failed");
        exit(EXIT_FAILURE);
    }
    printf("Thread joined\n");
    pthread_mutex_destroy(&work_mutex);
    exit(EXIT_SUCCESS);
}
/*主线程首先锁定工作区,在获取输入的字符后,释放工作区,让其他线程对字符个数进行统计。work_area[0[为空字符时表示统计结束。通过周期性地对互斥量进行加锁,检查是否已经统计完。*/
/*在线程中要执行的代码*/
void *thread_function(void *arg) {
    sleep(1);
    pthread_mutex_lock(&work_mutex);
    while(strncmp("end", work_area, 3) != 0) {
        printf("你输入了 %d 个字符\n", strlen(work_area) -1);
        work_area[0] = '\0';
        pthread_mutex_unlock(&work_mutex);
        sleep(1);
        pthread_mutex_lock(&work_mutex);
      
        while (work_area[0] == '\0' ) {
            pthread_mutex_unlock(&work_mutex);
            sleep(1);
            pthread_mutex_lock(&work_mutex);
        }
    }
    time_to_exit = 1;
    work_area[0] = '\0';
    pthread_mutex_unlock(&work_mutex);
    pthread_exit(0);
}

/*在新线程一上来先试图对互斥量进行加锁。如果它已经被锁上,新线程就会进入堵塞状态知道互斥锁释放为止,

一旦可以进入工作区,就先检查是否有退出请求(end)如果有,就设置time_to_exit变量和work_area,然后退出程序。

如果没有退出,那么就对字符个数进行统计。把work_area[0]设置为空,表示统计工作完成。接下来就释放互斥锁,

等待主线程的运行,周期性地给互斥量加锁,如果加锁成功,就检查主线程是否又给我们新的字符串统计。如果没有,

就释放互斥锁继续等待,*/

编译执行:gcc -D_REENTRANT fork.c -o fork -lpthread

运行结果如下:

参考文献:Linux程序设计

 

打赏

发表评论

电子邮件地址不会被公开。