多线程互斥锁读写锁

Posted go-ahead-wsg

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多线程互斥锁读写锁相关的知识,希望对你有一定的参考价值。

/*Linux环境编程:从应用到内核*/

/*
0.4.3 线程安全
线程安全,顾名思义是指代码可以在多线程环境下“安全”地执行。何为安全?即符合正确的逻辑结果,是程序员
期望的正常执行结果。为了实现线程安全,该代码要么只能使用局部变量或资源,要么就是利用锁等同步机制,来
实现全局变量或资源的串行访问。

6.1信号的完整声明周期
信号的本质是一种进程间的通信。进程之间约定好:如果发生了某件事情T(trigger),就向目标进程(destination
 process)发送某特定信号X,而目标进程看到X,就意识到T事件发生了,目标进程就会执行相应的动作A(action)。

总结:Linux的signal机制是一种原始的进程间通信机制,传递信息有限,很难传递复杂的消息,加上信号处理函数和
进程处于两条执行逻辑流,会带来函数的重入问题,因此signal机制不适合作为进程间通信的主要手段。但是
信号又不是完全无用的,对于某些不频繁发生的异步事件,还是可以使用signal来通知进程。 
*/

/*
7 理解linux线程

设计多线程的原因:
发挥多核优势,充分利用CPU资源
更自然的编程模型:很多程序,天生就适合用多线程。将工作切分成多个模块,并为每个模块分配一个或多个
执行单元,更符合人类解决问题的思路。

多线程存在的弊端:
多个线程之中,只要有一个线程不够健壮存在bug(如访问了非法地址引发的段错误),就会导致进程内的所有
线程一起完蛋。
线程模型作为一种并发的编程模型,效率并没有想象的那么高,会出现复杂度高、易出错、难以测试和定位问题。

多线程之间存在负载均衡的问题;
多个线程之间需要同步:若多个线程操作共享资源,则需要同步;因此多线程编程中存在临界区的概念,临界区
的代码只允许一个线程执行,线程提供了锁机制来保护临界区。当其他线程来到临界区却无法申请到锁时,就可能
陷入阻塞,不再处于可执行状态。

有人曾经这样打比方:“多进程属于立体交通系统,虽然造价高,上坡下坡比较耗油,但是堵车少;多线程属于平面
交通系统,造价低,但是红绿灯太多,老堵车”。

表7-4 POSIX线程库的接口
POSIX函数                           函数功能描述
pthread_create                  创建一个线程
pthread_exit                    退出线程
pthread_self                    获取线程ID
pthread_equal                   检查两个线程ID是否相等
pthread_join                    等待线程退出
pthread_detach                  设置线程状态为分离状态
pthread_cancel                  线程的取消
pthread_cleanup_push/pthread_cleanup_pop  线程退出,清理函数注册和执行   

线程创建销毁的流程
Main Thraed->pthread_ceate()->Thread->pthread_exit()->pthread_join()->exit()
不连接(pthread_join)已经退出的线程,会导致资源无法释放。

互斥量
为什么需要互斥量? 大部分情况下,线程使用的数据都是局部变量,变量的地址在线程栈空间内,这种情况下,
变量归属于单个线程,其他线程无法获取这种变量。
但实际情况是,很多变量都是多个线程共享的,这样的变量称为共享变量。可通过数据的共享,完成多个线程之间
的交互。
*/
//多线程及互斥锁代码
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#define LOOP_TIMES 10000000
#define NR_THREAD 4
pthread_rwlock_t rwlock;
pthread_mutex_t mutex;
int global_cnt = 0; //共享变量
void* thread_work(void* param)
{
    int i;
    pthread_rwlock_rdlock(&rwlock);
    for(i=0; i < LOOP_TIMES; i++)
    {
        pthread_mutex_lock(&mutex);     //互斥量加锁
        global_cnt++;
        pthread_mutex_unlock(&mutex);   //互斥量关锁
    }
    pthread_rwlock_unlock(&rwlock);
    return NULL;
}
int main(int argc, char* argv[])
{
    pthread_t tid[NR_THREAD];
    char err_buf[1024];
    int i, ret;
    ret=pthread_rwlock_init(&rwlock, NULL);     //读写锁
    if(ret)
    {
        fprintf(stderr, "init rw lock failed (%s)
", strerror_r(ret, err_buf, sizeof(err_buf)));
        exit(1);
    }
    ret=pthread_mutex_init(&mutex, NULL);
    if(ret)
    {
        fprintf(stderr, "init mutex lock failed (%s)
", strerror_r(ret, err_buf, sizeof(err_buf)));
        exit(1);
    }
    pthread_rwlock_wrlock(&rwlock);
    for(i=0; i<NR_THREAD; i++)
    {
        ret = pthread_create(&tid[i], NULL, thread_work, NULL);
        if(ret != 0)
        {
            fprintf(stderr, "create thread failed, return %s
", 
                            strerror_r(ret, err_buf, sizeof(err_buf)));
            exit(1);
        }
    }
    pthread_rwlock_unlock(&rwlock);     //子线程创建完成,主线程的读写锁关闭,4个线程同时启动
    for(i=0; i<NR_THREAD; i++)
    {
        pthread_join(tid[i], NULL);     //等待所有线程任务完成;
    }
    pthread_mutex_destroy(&mutex);
    pthread_rwlock_destroy(&rwlock);
    printf("threadnum:  %d
",NR_THREAD);
    printf("loops per thrad: %d
",LOOP_TIMES);
    printf("expect result: %d
", LOOP_TIMES*NR_THREAD);
    printf("actual result: %d
", global_cnt);
    exit(0);
}
/*
注意事项:
1.编译方法:gcc mutex.c -o mutex  -lpthread
pthread 库不是 Linux 系统默认的库,连接时需要使用静态库 libpthread.a
所以在使用pthread_create()创建线程,及pthread_rwlock*读写锁,处理程序时,需要链接该库
2.互斥量和读写锁使用完成后都要手动销毁
*/

/*
7.8读写锁
很多时候,对共享变量的访问有以下特点:大多数情况下线程只是读取共享变量的值,并不修改,只有极少数情况下,线程才会真正的修改共享变量的值。
对于这种情况,读请求之间是无需同步的,它们之间的并发访问是安全的。然而写请求必须锁住读请求和其他请求。
这种情况在实际中是存在的,比如配置项。大多数时间内,配置是不会发生变化的,偶尔会出现修改配置的情况。如果使用互斥量,完全阻止请求并发,则会
造成性能损失。
*/

 

以上是关于多线程互斥锁读写锁的主要内容,如果未能解决你的问题,请参考以下文章

Linux多线程中互斥锁读写锁自旋锁条件变量信号量详解

锁详解区分 互斥锁⾃旋锁读写锁乐观锁悲观锁

多线程 锁策略 ( 悲观/乐观锁 读写/互斥锁 重量/轻量级锁挂起等待/自旋锁 公平/非公平锁 可重入/不可重入锁)

Java 线程锁机制 -Synchronized Lock 互斥锁 读写锁

多线程之线程同步(互斥锁信号量条件变量和读写锁​)

多线程之线程同步(互斥锁信号量条件变量和读写锁​)