1. 程式人生 > >Linux使用互斥鎖和條件變數實現讀寫鎖(寫優先)

Linux使用互斥鎖和條件變數實現讀寫鎖(寫優先)

(1)只要沒有執行緒持有某個給定的讀寫鎖用於寫,那麼任意數目的執行緒可以持有該讀寫鎖用於讀

(2)僅當沒有執行緒持有某個讀寫鎖用於讀或用於寫時,才能分配該讀寫鎖用於寫

換一種說法就是,只要沒有執行緒在修改(寫)某個給定的資料,那麼任意數目的執行緒都可以擁有該資料的訪問權(讀)。僅當沒有其它執行緒在讀或者修改(寫)某個給定的資料時,當前執行緒才可以修改(寫)它。

因此,讀為共享,寫為獨佔。

本程式只實現了一種可能,即優先考慮等待著的寫入者,可有其他實現方案。

//my_pthread_rwlock.h

#pragma once

#include<pthread.h>
#include<stdio.h>

typedef struct
{
    pthread_mutex_t rw_mutex;
    pthread_cond_t  rw_condreaders;
    pthread_cond_t  rw_condwriters;
    int             rw_magic;
    int             rw_nwaitreaders;
    int             rw_nwaitwriters;
    int             rw_refcount;       // 0 >0 ==-1
}my_pthread_rwlock_t;

#define  RW_MAGIC  0x20180326
#define  EBUSY 22
#define MY_PTHREAD_RWLOCK_INITIALIZER {PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER,\
RW_MAGIC,0,0,0}

typedef int  my_pthread_rwlockattr_t;


int my_pthread_rwlock_init(my_pthread_rwlock_t *rw, my_pthread_rwlockattr_t *attr);
int my_pthread_rwlock_destroy(my_pthread_rwlock_t *rw);
int my_pthread_rwlock_rdlock(my_pthread_rwlock_t *rw);
int my_pthread_rwlock_wrlock(my_pthread_rwlock_t *rw);
int my_pthread_rwlock_unlock(my_pthread_rwlock_t *rw);
int my_pthread_rwlock_tryrdlock(my_pthread_rwlock_t *rw);
int my_pthread_rwlock_trywrlock(my_pthread_rwlock_t *rw);

//my_pthread_rwlock.c

#include"my_pthread_rwlock.h"
#include<pthread.h>
int my_pthread_rwlock_init(my_pthread_rwlock_t *rw, my_pthread_rwlockattr_t *attr)
{
	int result;
	if(attr != NULL)
		return -1;
	if((result = pthread_mutex_init(&rw->rw_mutex,NULL))!=0)
		goto err1;
	if((result = pthread_cond_init(&rw->rw_condreaders,NULL))!=0)
		goto err2;
	if((result = pthread_cond_init(&rw->rw_condwriters,NULL))!=0)
		goto err3;
	rw->rw_nwaitreaders=0;
	rw->rw_nwaitwriters=0;
	rw->rw_refcount=0;
	rw->rw_magic=RW_MAGIC;
	return 0;
err3:pthread_cond_destory(&rw->rw_condreaders);
err2:pthread_mutex_destory(&rw->rw_mutex);
err1:return result;

}
int my_pthread_rwlock_rdlock(my_pthread_rwlock_t *rw)
{
    int result;
    if(rw->rw_magic != RW_MAGIC)
        return -1;
    if((result = pthread_mutex_lock(&rw->rw_mutex)) != 0)
        return result;

    while(rw->rw_refcount<0 || rw->rw_nwaitwriters>0)
    {
        rw->rw_nwaitreaders++;
        result = pthread_cond_wait(&rw->rw_condreaders, &rw->rw_mutex);
        rw->rw_nwaitreaders--;
        if(result != 0)
            break;
    }
    if(result == 0)
        rw->rw_refcount++;
    pthread_mutex_unlock(&rw->rw_mutex);
    return result;
}

int my_pthread_rwlock_wrlock(my_pthread_rwlock_t *rw)
{
    int result;
    if(rw->rw_magic != RW_MAGIC)
        return -1;

    if((result = pthread_mutex_lock(&rw->rw_mutex)) != 0)
        return result;

    while(rw->rw_refcount != 0)
    {
        rw->rw_nwaitwriters++;
        result = pthread_cond_wait(&rw->rw_condwriters, &rw->rw_mutex);
        rw->rw_nwaitwriters--;
        if(result != 0)
            break;
    }
    if(result == 0)
        rw->rw_refcount = -1;

    pthread_mutex_unlock(&rw->rw_mutex);
    return result;
}

int my_pthread_rwlock_unlock(my_pthread_rwlock_t *rw)
{
    int result;
    if(rw->rw_magic != RW_MAGIC)
        return -1;
    if((result = pthread_mutex_lock(&rw->rw_mutex)) != 0)
        return result;

    if(rw->rw_refcount > 0)
        rw->rw_refcount--;
    else if(rw->rw_refcount == -1)
        rw->rw_refcount = 0;
    else
        printf("unlock error.\n");

    if(rw->rw_nwaitwriters > 0)
    {
        if(rw->rw_refcount == 0)
        {
            result = pthread_cond_signal(&rw->rw_condwriters);
        }
    }
    else if(rw->rw_nwaitreaders > 0)
        result = pthread_cond_broadcast(&rw->rw_condreaders);

    pthread_mutex_unlock(&rw->rw_mutex);
    return result;
}
int my_pthread_rwlock_tryrdlock(my_pthread_rwlock_t *rw)
{
	int result;
	if(rw->rw_magic!=RW_MAGIC)
		return -1;
	if((result = pthread_mutex_lock(&rw->rw_mutex))!=0)
		return result;
	if(rw->rw_refcount!=0||rw->rw_nwaitwriters>0)
		result=EBUSY;
	else
		rw->rw_refcount++;
	return result;
}
int my_pthread_rwlock_trywrlock(my_pthread_rwlock_t *rw)
{
	int result;
	if(rw->rw_magic!=RW_MAGIC)
		return -1;
	if((result = pthread_mutex_lock(&rw->rw_mutex))!=0)
		return result;
	if(rw->rw_refcount!=0)
		result=EBUSY;
	else
		rw->rw_refcount=-1;
	pthread_mutex_unlock(&rw->rw_mutex);
	return result;
}
int my_pthread_rwlock_destroy(my_pthread_rwlock_t *rw)
{
	if(rw->rw_magic!=RW_MAGIC)
		return -1;
	if(rw->rw_refcount!=0||rw->rw_nwaitreaders!=0||rw->rw_nwaitwriters!=0)
		return EBUSY;
	pthraed_mutex_destory(&rw->rw_mutex);
	pthread_cond_destory(&rw->rw_condreaders);
	pthread_cond_destory(&rw->rw_condwriters);
	rw->rw_magic=0;
	return 0;

}

//main.c

#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
#include"my_pthread_rwlock.h"

my_pthread_rwlock_t rwlock = MY_PTHREAD_RWLOCK_INITIALIZER;

void * thread_fun1(void *arg)
{
}
void * thread_fun2(void *arg)
{
}
void * thread_fun3(void *arg)
{ 
}

int main()
{
    pthread_t tid1, tid2, tid3;
    pthread_create(&tid1, NULL, thread_fun1, NULL);
    sleep(1);
    pthread_create(&tid2, NULL, thread_fun2, NULL);
    pthread_create(&tid3, NULL, thread_fun3, NULL);

    pthread_join(tid1, NULL);
    pthread_join(tid2, NULL);
    pthread_join(tid3, NULL);
    return 0;
}

相關推薦

Linux使用互斥條件變數實現優先

(1)只要沒有執行緒持有某個給定的讀寫鎖用於寫,那麼任意數目的執行緒可以持有該讀寫鎖用於讀(2)僅當沒有執行緒持有某個讀寫鎖用於讀或用於寫時,才能分配該讀寫鎖用於寫換一種說法就是,只要沒有執行緒在修改(寫)某個給定的資料,那麼任意數目的執行緒都可以擁有該資料的訪問權(讀)。僅

通過互斥條件變數實現佇列的無sleep生產與消費

昨天轉了一篇文章將條件變數與互斥鎖的結合使用,今天給大家摳出曾經學到的一段高效的處理訊息的demo,通過互斥鎖實現安全佇列,通過條件變數實現佇列的工作與休息。 目錄結構: 簡單介紹: SignalThread是封裝好的執行緒類,我們所做的核心工作都是在這裡完成,其他類也是服務於這裡;

多執行緒用互斥條件變數實現生產者消費者-------迴圈任務佇列

互斥鎖與條件變數簡介 在多執行緒的環境中,全域性變數會被各執行緒共享,因此在操作全域性變數的時候需要採用鎖機制,在linux裡最常用的鎖就是互斥鎖,互斥鎖使用方法如下 <pre name="code" class="cpp">//執行緒A pthread_mut

互斥條件變數實現生產者消費者模型

/*producer and constmer*/ #include<stdio.h> #include<pthread.h> #include<string.h>

linux下用互斥條件變數實現

以下內容來源自UNP卷二的第八章 讀寫鎖的概念( the conception of read-write lock ) (1)只要沒有執行緒持有某個給定的讀寫鎖用於寫,那麼任意數目的執行緒可以持有該執行緒用於讀 (2)僅當沒有執行緒持有某個給定的讀寫鎖用於讀或用於寫,才能分配該

訊號量、互斥條件變數之間的區別

訊號量 強調的是執行緒(或程序)間的同步:“訊號量用在多執行緒多工同步的,一個執行緒完成了某一個動作就通過訊號量告訴別的執行緒,別的執行緒再進行某些動作(大家都在sem_wait的時候,就阻塞在那裡)。當訊號量為單值訊號量是,也可以完成一個資源的互斥訪問。 有名

Linux多執行緒學習(2)--執行緒的同步與互斥及死問題(互斥條件變數)

Linux多執行緒學習總結 一.互斥量 1.名詞理解 2.什麼是互斥量(mutex) 3.互斥量的介面 3.1 初始化訊號量 3.2 銷燬訊號量 3.3 互斥量加鎖和解鎖

Linux程序通訊[2]-互斥條件變數

概述 上一篇介紹了共享記憶體,已經屬於比較高階的層次。本篇介紹一下多執行緒/多程序最基礎的問題,同步。 為了允許線上程或程序間共享資料,同步常常是必需的,也就是我們常說要用鎖(當然鎖通常也是效能瓶頸,現在無鎖架構正在越發流行)。互斥鎖和條件變數則是同步的基本組成部分。互斥鎖和條件變數在同一程序下的所有

Linux C互斥條件變數POSIX標準

       與程序類似,執行緒也存在同步的問題,當多個控制執行緒共享相同的記憶體時,需要確保每個執行緒看到一致的資料檢視,如果每個執行緒使用的變數都是其他執行緒不會讀取或修改的(比如執行緒私有資料),就不會存在一致性問題。通常來說使用者可以使用互斥量(互斥鎖)或者的條件變數

Linux多執行緒消費者生產者模型例項互斥條件變數使用

條件變數簡單介紹: 條件變數是執行緒可以使用的另一種同步機制。條件變數與互斥量一起使用的時候,允許執行緒以無競爭的方式等待特定的條件發生。條件本身是由互斥量保護的。執行緒在改變條件變數狀態前必須先鎖住互斥量。另一種是動態分配的條件變數,則用pthread_cond_ini

Linux下多執行緒程式設計互斥條件變數的簡單使用

Linux下的多執行緒遵循POSIX執行緒介面,稱為pthread。編寫Linux下的多執行緒程式,需要使用標頭檔案pthread.h,連結時需要使用庫libpthread.a。執行緒是程序的一個實體,是CPU排程和分派的基本單位,它是比程序更小的能獨立執行的基本單位。執行緒

執行緒私有資料TSD——一鍵多值技術,執行緒同步中的互斥條件變數

一:執行緒私有資料: 執行緒是輕量級程序,程序在fork()之後,子程序不繼承父程序的鎖和警告,別的基本上都會繼承,而vfork()與fork()不同的地方在於vfork()之後的程序會共享父程序的地址空間,但是有了寫實複製(fork()之後的子程序也不會直接

C++ 併發程式設計之互斥條件變數的效能比較

介紹 本文以最簡單生產者消費者模型,通過執行程式,觀察該程序的cpu使用率,來對比使用互斥鎖 和 互斥鎖+條件變數的效能比較。 本例子的生產者消費者模型,1個生產者,5個消費者。 生產者執行緒往佇列裡放入資料,5個消費者執行緒從佇列取資料,取資料前需要判斷一下佇列中是否有資料,這個佇列是全域性佇列,是執行緒間

【Java併發程式設計】之二十:併發新特性—Lock條件變數含程式碼

簡單使用Lock鎖     Java 5中引入了新的鎖機制——java.util.concurrent.locks中的顯式的互斥鎖:Lock介面,它提供了比synchronized更加廣泛的鎖定操作。Lock介面有3個實現它的類:ReentrantLock、Reetrant

關於互斥條件變數

條件變數一般用於阻塞執行緒以及給執行緒發訊號,解除阻塞。而條件變數往往和互斥量一起使用,因為條件變數在阻塞的時候會有一個加鎖解鎖的過程。還記得以前寫過一個生產者——消費者的例項,那時候對一些問題還不是很理解。下面是一個簡單的練習例項,以及最後總結遇到的一些問題。

互斥條件變數

1、如何利用2個條件變數實現執行緒同步?  思路:就是來回的利用pthread_cond_signal()函式,當一方被阻塞時,喚醒函式可以喚醒pthread_cond_wait()函式,只不過pthread_cond_wait()這個方法要執行其後的語句,必須遇到下一個阻塞

windows 使用關鍵段條件變數實現的生產者消費者執行緒同步

 關鍵段比較簡單,呼叫函式如下: VOID InitializeCriticalSection( LPCRITICAL_SECTION );//初始化一個關鍵程式碼段 VOID EnterCriticalSection( LPCRITICAL_SECTION);//獲取

linux 各個目錄相關文件的作用等 混亂版初學者自用

nac 歷史 沒有 The 用戶配置 相關 file 文件 prot t權限 /etc/profile文件當一個用戶登陸linux系統或者使用su命令切換到另一個用戶時,也就是login shell啟動時首先要保證執行的啟動腳本就是/etc/profile ??/etc/

[Linux]通過使用者名稱密碼的方式搭建Git伺服器http&gitweb

1、安裝依賴 yum -y install perl cpio autoconf tk zlib-devel libcurl-devel openssl-devel expat-devel yum install perl-ExtUtils-CBuilder

Linux多執行緒程式設計---執行緒間同步互斥條件變數、訊號量

本篇博文轉自http://zhangxiaoya.github.io/2015/05/15/multi-thread-of-c-program-language-on-linux/ Linux下提供了多種方式來處理執行緒同步,最常用的是互斥鎖、條件變數、訊號量和讀寫鎖。  下面是思維導