zoukankan      html  css  js  c++  java
  • 线程同步之读写锁(锁操作的补充)

    轻量级的读写锁(Slim Reader-Writer locks):读写锁实际是一种特殊的自旋锁,它把对共享资源的访问者划分成读者和写者,读者只对共享资源进行读访问,写者则需要对共享资源进行写操作。
    这种锁相对于自旋锁而言,能提高并发性,因为在多处理器系统中,它允许同时有多个读者来访问共享资源,最大可能的读者数为实际的逻辑CPU数。
    写者是排他性的,一个读写锁同时只能有一个写者或多个读者(与CPU数相关),但不能同时既有读者又有写者。

    读写锁比起mutex具有更高的适用性,具有更高的并行性,可以有多个线程同时占用读模式的读写锁,但是只能有一个线程占用写模式的读写锁,读写锁的三种状态:
    1.当读写锁是写加锁状态时,在这个锁被解锁之前,所有试图对这个锁加锁的线程都会被阻塞
    2.当读写锁在读加锁状态时,所有试图以读模式对它进行加锁的线程都可以得到访问权,但是以写模式对它进行加锁的线程将会被阻塞
    3.当读写锁在读模式的锁状态时,如果有另外的线程试图以写模式加锁,读写锁通常会阻塞随后的读模式锁的请求,这样可以避免读模式锁长期占用,而等待的写模式锁请求则长期阻塞。

    SRW代表-------Slim Reader-Writer

    函数解析:

    1.// 初始化读写锁
    VOID WINAPI InitializeSRWLock
    (
      __out PSRWLOCK SRWLock
    );
    函数功能:初始化读写锁


    2.// 独占式访问
    VOID WINAPI AcquireSRWLockExclusive

    (
      __inout PSRWLOCK SRWLock
    );
    函数功能:写入者线程申请写资源。


    3.// 独占式释放
    VOID WINAPI ReleaseSRWLockExclusive

    (
      __inout PSRWLOCK SRWLock
    );
    函数功能:写入者线程写资源完毕,释放对资源的占用。


    4.// 共享式访问
    VOID WINAPI AcquireSRWLockShared

    (
      __inout PSRWLOCK SRWLock
    );
    函数功能:读取者线程申请读资源。

    5.// 共享式释放
    VOID WINAPI ReleaseSRWLockShared

    (
      __inout PSRWLOCK SRWLock
    );
    函数功能:读取者线程结束读取资源,释放对资源的占用。

    注意点:
    1.访问方式只能选择其一,不可以同时使用。即一个线程仅能锁定资源一次,不能多次锁定资源。
    2.读写锁声明后要初始化,但不用销毁,系统会自动清理读写锁。
    3.读取者和写入者分别调用不同的申请函数和释放函数。

    区别:
    1.AcquireSRWLockExclusive抢占式的,当线程上锁后,其他线程无法进行访问。直到 ReleaseSRWLockExclusive,释放后。一般用于写操作。
    2.AcquireSRWLockShared 是共享式的,即使线程上锁后,其他线程也可以进行再次访问。一般用于读操作。

    源代码:
    // Semaphore.cpp : 定义控制台应用程序的入口点。
    //
    #include "stdafx.h"
    #include <Windows.h>
    #include <process.h>
    
    //线程数
    #define  g_nThreadNum 3
    
    //信号量
    SRWLOCK g_srwLock;
    
    //累加数
    int g_nCount = 50;
    
    unsigned _stdcall WriteThread(void * lParam)
    {
        
        // 独占式访问
        AcquireSRWLockExclusive(&g_srwLock);
        
        g_nCount++;
        
        // 独占式释放
        ReleaseSRWLockExclusive(&g_srwLock);
        
        return 0;
    }
    
    unsigned _stdcall ReadThread(void *lParam)
    {
        // 共享式访问
        AcquireSRWLockShared(&g_srwLock);
        
        printf("g_nCount=%d
    ", g_nCount);
        
        // 共享式释放
        ReleaseSRWLockShared(&g_srwLock);
    
        return 0;
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        //// 初始化读写锁
        InitializeSRWLock(&g_srwLock);
        //启动线程
        HANDLE pThread[g_nThreadNum];
        
        pThread[0] = (HANDLE)_beginthreadex(NULL, 0, ReadThread, NULL, 0, 0);
        
        pThread[1] = (HANDLE)_beginthreadex(NULL, 0, WriteThread, NULL, 0, 0);
    
        pThread[2] = (HANDLE)_beginthreadex(NULL, 0, ReadThread, NULL, 0, 0);
        
        //等待线程结束
        WaitForMultipleObjects(g_nThreadNum, pThread, TRUE, INFINITE);
    
        printf("g_nCount:%d
    ", g_nCount);
    
        //释放资源
        for (int i = 0; i < g_nThreadNum; ++i)
        {
            CloseHandle(pThread[i]);
        }
        
        getchar();
        return 0;
    }
  • 相关阅读:
    [转]VC++下使用ADO操作数据库
    VC++ GetSafeHwnd()和GetSafeHandle()
    VC++ GetSafeHwnd用法
    C++中的const成员函数(函数声明后加const,或称常量成员函数)用法详解
    VC++ Debug条件断点使用
    VC++为你的程序增加内存泄露检测
    VC++ Debug格式化数值显示
    VC++Debug查看堆对象内容,即使符号已经超出作用范围
    VC++ Debug产生异常时中断程序执行Break on Exception
    一个简单的伪随机数发生算法
  • 原文地址:https://www.cnblogs.com/gd-luojialin/p/7694143.html
Copyright © 2011-2022 走看看