linux互斥锁(pthread_mutex)知识点总结

简介: linux互斥锁(pthread_mutex)知识点总结

对于多线程程序来说,我们往往需要对这些多线程进行同步。同步(synchronization)是指在一定的时间内只允许某一个线程访问某个资源。而在此时间内,不允许其它的线程访问该资源。我们可以通过互斥锁(mutex),条件变量(condition variable)和读写锁(reader-writer lock)来同步资源。


与互斥锁相关API

 互斥量(mutex)从本质上来说是一把锁,在访问共享资源前对互斥量进行加锁,在访问完成后释放互斥量上的锁。对互斥量进行加锁后,任何其他试图再次对互斥量加锁的线程将会被阻塞直到当前线程释放该互斥锁。如果释放互斥锁时有多个线程阻塞,所有在该互斥锁上的阻塞线程都会变成可运行状态,第一个变为可运行状态的线程可以对互斥量加锁,其他线程将会看到互斥锁依然被锁住,只能回去等待它重新变为可用。在这种方式下,每次只有一个线程可以向前运行。


 在设计时需要规定所有的线程必须遵守相同的数据访问规则。只有这样,互斥机制才能正常工作。操作系统并不会做数据访问的串行化。如果允许其中的某个线程在没有得到锁的情况下也可以访问共享资源,那么即使其它的线程在使用共享资源前都获取了锁,也还是会出现数据不一致的问题。


 互斥变量用pthread_mutex_t数据类型表示。在使用互斥变量前必须对它进行初始化,可以把它置为常量PTHREAD_MUTEX_INITIALIZER(只对静态分配的互斥量),也可以通过调用pthread_mutex_init函数进行初始化。如果动态地分配互斥量(例如通过调用malloc函数),那么在释放内存前需要调用pthread_mutex_destroy。


1. 创建及销毁互斥锁


#include <pthread.h>
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
int pthread_mutex_destroy(pthread_mutex_t *mutex);
// 返回:若成功返回0,否则返回错误编号

要用默认的属性初始化互斥量,只需把attr设置为NULL。  


2. 加锁及解锁

#include <pthread.h>
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
// 返回:若成功返回0,否则返回错误编号

 如果线程不希望被阻塞,它可以使用pthread_mutex_trylock尝试对互斥量进行加锁。如果调用pthread_mutex_trylock时互斥量处于未锁住状态,那么pthread_mutex_trylock将锁住互斥量,不会出现阻塞并返回0,否则pthread_mutex_trylock就会失败,不能锁住互斥量,而返回EBUSY。


示例代码:

#include <stdio.h>
#include <pthread.h>
 
//int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);
int g_data = 0;
 
 
pthread_mutex_t mutex;
 
 
void *func1(void *arg)
{
    int i;
 
    pthread_mutex_lock(&mutex);
    for(i=0;i<5;i++){
        printf("t1:%ld thread is create\n",(unsigned long)pthread_self());
        printf("t1:param is %d\n",*((int *)arg));
        sleep(1);
    }
    pthread_mutex_unlock(&mutex);
 
}
 
void *func2(void *arg)
{
 
    pthread_mutex_lock(&mutex);
 
    printf("t2:%ld thread is create\n",(unsigned long)pthread_self());
    printf("t2:param is %d\n",*((int *)arg));
 
    pthread_mutex_unlock(&mutex);
 
}
 
void *func3(void *arg)
{
 
    pthread_mutex_lock(&mutex);
 
    printf("t3:%ld thread is create\n",(unsigned long)pthread_self());
    printf("t3:param is %d\n",*((int *)arg));
 
    pthread_mutex_unlock(&mutex);
 
}
 
int main()
{
    int ret;
    int param = 100;
    pthread_t t1;
    pthread_t t2;
    pthread_t t3;
 
    pthread_mutex_init(&mutex, NULL);
 
    
    ret = pthread_create(&t1, NULL, func1,(void *)&param);
    if(ret == 0){
        printf("main:create t1 success\n");
    }
 
    ret = pthread_create(&t2, NULL, func2,(void *)&param);
    if(ret == 0){
        printf("main:create t2 success\n");
    }
 
    ret = pthread_create(&t3, NULL, func3,(void *)&param);
    printf("main:%ld\n",(unsigned long)pthread_self());
 
    pthread_join(t1,NULL);
    pthread_join(t2,NULL);
 
    pthread_mutex_destroy(&mutex);
 
    return 0;
}

编译结果:t1会被main函数打断,但是不会被t2,t3打断,t1运行后t2,t3才能运行

我们也用互斥锁限制共享资源的访问

例如:让g_data = 3时,在线程t1退出

#include <stdio.h>
#include <pthread.h>
 
//int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);
int g_data = 0;
 
pthread_mutex_t mutex;
 
 
void *func1(void *arg)
{
    printf("t1:%ld thread is create\n",(unsigned long)pthread_self());
    printf("t1:param is %d\n",*((int *)arg));
    
    pthread_mutex_lock(&mutex);
    while(1){
 
 
        printf("t1: %d\n",g_data++);    
        sleep(1);
 
        if(g_data == 3){
            pthread_mutex_unlock(&mutex);
            printf("t1 quit================================\n");
//            pthread_exit(NULL);
            exit(0);
        }
    }
 
}
 
void *func2(void *arg)
{
    printf("t2:%ld thread is create\n",(unsigned long)pthread_self());
    printf("t2:param is %d\n",*((int *)arg));
    
    
    while(1){
 
        printf("t2: %d\n",g_data);
        pthread_mutex_lock(&mutex);
        g_data++;
        pthread_mutex_unlock(&mutex);    
        sleep(1);
    }
}
 
int main()
{
    int ret;
    int param = 100;
    pthread_t t1;
    pthread_t t2;
 
    pthread_mutex_init(&mutex,NULL);
 
    ret = pthread_create(&t1, NULL, func1,(void *)&param);
    if(ret == 0){
        printf("main:create t1 success\n");
    }
 
    ret = pthread_create(&t2, NULL, func2,(void *)&param);
    if(ret == 0){
        printf("main:create t2 success\n");
    }
 
    printf("main:%ld\n",(unsigned long)pthread_self());
    while(1){
    
        printf("main: %d\n",g_data);    
        sleep(1);
    }
 
    pthread_join(t1,NULL);
    pthread_join(t2,NULL);
    pthread_mutex_destroy(&mutex);
 
    return 0;
}

编译结果:

可以写个shell脚本验证一下编译结果,先简单介绍一下shell脚本吧

Shell脚本

Shell 脚本(shell script),是一种为 shell 编写的脚本程序。shell script是一种解释型语言,必须由解释器来执行这些脚本,执行时,解释器将脚本一行一行地转换为代码。


这个解释器就是Shell,它是一个用 C 语言编写的程序。常见的Shell有Bourne Shell(/usr/bin/sh或/bin/sh)和Bourne Again Shell(/bin/bash),sh由Steve Bourne开发,是Unix 标准默认的shell,bash由Brian Fox和Chet Ramey共同开发完成,是Linux标准默认的shell。



在linux中可以使用vim来编写shell script,通常使用.sh作为扩展名,sh代表shell。下面是一个简单的shell脚本:



//运行三次

编写完shell脚本,在执行脚本前我们需要给脚本添加执行权限,命令如下:

接着运行:

编译结果:

相关文章
|
8天前
|
Linux
|
2月前
|
监控 关系型数据库 MySQL
在Linux中,mysql的innodb如何定位锁问题?
在Linux中,mysql的innodb如何定位锁问题?
|
2月前
|
Linux API 调度
重温Linux内核:互斥和同步
本文全面回顾了Linux内核中的互斥和同步机制,包括中断屏蔽、原子变量、自旋锁、读写锁、顺序锁、信号量、互斥量、RCU机制以及完成量等,提供了它们的定义、实现原理、API用法和使用时的注意事项。
40 0
|
4月前
|
存储 网络协议 编译器
【干货总结】Linux C/C++面试知识点
Linux C/C++基础与进阶知识点,不仅用于面试,平时开发也用得上!
527 11
|
4月前
|
监控 Linux 数据处理
lslocks:Linux系统中的锁信息查看利器
`lslocks`是Linux工具,用于查看系统上的文件锁信息,帮助诊断进程同步问题。它显示持有锁的进程、锁类型(如POSIX、flock)和状态。通过简洁的输出,用户能识别死锁和资源争用,优化性能。结合其他命令如`grep`和`awk`可增强分析能力。需适当权限运行,定期监控以预防并发访问问题,处理死锁时要谨慎。
|
4月前
|
API
linux---线程互斥锁总结及代码实现
linux---线程互斥锁总结及代码实现
|
4月前
|
API
Linux---线程读写锁详解及代码实现
Linux---线程读写锁详解及代码实现
|
3月前
|
安全 算法 Linux
【Linux】线程安全——补充|互斥、锁|同步、条件变量(下)
【Linux】线程安全——补充|互斥、锁|同步、条件变量(下)
41 0
|
3月前
|
存储 安全 Linux
【Linux】线程安全——补充|互斥、锁|同步、条件变量(上)
【Linux】线程安全——补充|互斥、锁|同步、条件变量(上)
50 0
|
3月前
|
缓存 网络协议 Linux
Linux、Python、计算机网络中的常见知识点
Linux、Python、计算机网络中的常见知识点
下一篇
无影云桌面