进程读写锁和信号量

进程读写锁

Pthread_rwlockattr_setshared, 当将process-shared属性设为Pthread_process_shared时,可以得到一个进程间的读写锁,如果process-shared属性设为pthread_process_private, 那么能操作这个读写锁的线程只能是创建这个读写锁的进程中的线程, pthread_shared的默认值为pthread_process_private

int

__pthread_rwlock_rdlock (rwlock)

     pthread_rwlock_t *rwlock;

{

  int result = 0;

  /* Make sure we are along.  */

  lll_mutex_lock (rwlock->__data.__lock);

  while (1)

    {

      /* Get the rwlock if there is no writer...  */

      if (rwlock->__data.__writer == 0

         /* ...and if either no writer is waiting or we prefer readers.  */

         && (!rwlock->__data.__nr_writers_queued

             || rwlock->__data.__flags == 0))

       {

         /* Increment the reader counter.  Avoid overflow.  */

         if (__builtin_expect (++rwlock->__data.__nr_readers == 0, 0))

           {

             /* Overflow on number of readers. */

             --rwlock->__data.__nr_readers;

             result = EAGAIN;

           }

         break;

       }

      /* Make sure we are not holding the rwlock as a writer.  This is

        a deadlock situation we recognize and report.  */

      if (__builtin_expect (rwlock->__data.__writer

                         == THREAD_GETMEM (THREAD_SELF, tid), 0))

       {

         result = EDEADLK;

         break;

       }

      /* Remember that we are a reader.  */

      if (__builtin_expect (++rwlock->__data.__nr_readers_queued == 0, 0))

       {

         /* Overflow on number of queued readers.  */

         --rwlock->__data.__nr_readers_queued;

         result = EAGAIN;

         break;

       }

      int waitval = rwlock->__data.__readers_wakeup;

      /* Free the lock.  */

      lll_mutex_unlock (rwlock->__data.__lock);

      /* Wait for the writer to finish.  */

      lll_futex_wait (&rwlock->__data.__readers_wakeup, waitval);

      /* Get the lock.  */

      lll_mutex_lock (rwlock->__data.__lock);

      --rwlock->__data.__nr_readers_queued;

    }

  /* We are done, free the lock.  */

  lll_mutex_unlock (rwlock->__data.__lock);

  return result;

}

这是进程获取读锁的函数, 占有读写锁的锁后, __pthread_rwlock_rdlock首先看是否满足获取读锁的条件, 如果满足条件, 增加读者数,然后释放读写锁的锁, 然后退出

如果不满足获取读写锁的条件, 将等待的读者数增加, 释放读写锁的锁, 然后将进程睡眠, 等到写者退出时, 将进程唤醒, 重新占有读写锁的锁, 进行循环, 判断是不是满足占有读写锁的条件

写者获取读写锁的方式于此类似

信号量

struct semaphore {

       spinlock_t             lock;

       unsigned int         count;

       struct list_head     wait_list;

};

信号量的结构包含一个自旋锁,一个表示信号量的值count,和一个等待信号量的队列

对于信号量的操作是up和down函数

void up(struct semaphore *sem)

{

       unsigned long flags;

       spin_lock_irqsave(&sem->lock, flags);

       if (likely(list_empty(&sem->wait_list)))

              sem->count++;

       else

              __up(sem);

       spin_unlock_irqrestore(&sem->lock, flags);

}

Up函数检查信号量的等待队列是否为空, 如果没有等待的进程, 增加信号量, 如果有等待的进程, 唤醒等待的第一个进程

自旋锁等待的特性是不可中断的. 一旦调用 spin_lock, 你将自旋直到锁变为可用,所以持有自旋锁的程序的一个很重要的一点是不能睡眠

自旋锁需要尽可能短地时间去持有, 一个进程持有自旋锁的时间越长, 另一个进程等待释放的时间就越长

信号量中up函数中调用的spin_lock_irqsave函数是禁止在持有自旋锁时中断的, 并且会将中断状态保存在flags中

在down函数中调用__down, 如果信号量为0, __down会把当前进程加入等待列表, 然后解除该进程对信号量的锁, 调用schedule_timeout使进程睡眠, 超时唤醒后, 再对信号量加锁,进入循环

时间: 2024-12-20 05:46:12

进程读写锁和信号量的相关文章

QThread中的互斥、读写锁、信号量、条件变量

该文出自:http://www.civilnet.cn/bbs/browse.php?topicno=78431 在gemfield的<从pthread到QThread>一文中我们了解了线程的基本使用,但是有一大部分的内容当时说要放到这片文章里讨论,那就是线程的同步问题.关于这个问题,gemfield在<从进 程到线程>中有一个比喻,有必要重新放在下面温习下: ******************************* 最后用一个比喻来总结下: 1.一个进程就好比一个房子里有一

Java实现锁、公平锁、读写锁、信号量、阻塞队列、线程池等常用并发工具

锁的实现 锁的实现其实很简单,主要使用Java中synchronized关键字. public class Lock { private volatile boolean isLocked = false; private Thread lockingThread = null; public synchronized void lock() throws InterruptedExpection { while(isLocked){ wait(); } isLocked = true; loc

信号量、互斥锁,读写锁和条件变量的区别

信号量强调的是线程(或进程)间的同步:“信号量用在多线程多任务同步的,一个线程完成了某一个动作就通过信号量告诉别的线程,别的线程再进行某些动作(大家都 在sem_wait的时候,就阻塞在那里).当信号量为单值信号量是,也可以完成一个资源的互斥访问.有名信号量:可以用于不同进程间或多线程间的互斥与同步 创建打开有名信号量 sem_t *sem_open(const char *name, int oflag); sem_t *sem_open(const char *name, int oflag

用信号量和读写锁解决读者写者问题

读者写者问题是非常经典的同步问题,本文首先用信号量来解决这个问题,并结合代码分析什么是读者优先.什么是写者优先,然后给出读写锁的解决方案,并指出在Linux下读写锁的注意事项. 读者写者问题 读者写者问题描述的是这么一种情况:对象在多个线程(或者进程)之间共享,其中一些线程只会读数据,另外一些线程只会写数据.为了保证写入和读取的正确性,我们需要保证,只要有线程在写,那么其他线程不能读,否则可能读到写了一半的数据:另外,也不能有两个线程同时写,否则导致数据错乱.当然,多个线程是可以同时读数据. 读

互斥锁,信号量,条件变量,读写锁

互斥锁 互斥锁的特性: 1. 原子性:当有一个线程成功拿到了这个锁,其他线程都无法在相同的时间拿到这个锁 2. 唯一性:在一个线程拿到锁的这段时间,只有当这个线程把锁释放掉,其他的线程才有可能拿到 3. 非繁忙等待性:如果一个线程已经锁定了一个互斥量,第二个线程又视图去拿到这个锁的前线,则第二个锁将被挂起,等待第一个线程对互斥量解锁位置,同时第二个线程获取锁,继续往下执行 pthread_mutex_init pthread_mutex_lock pthread_mutex_trylock pt

C#使用读写锁三句代码简单解决多线程并发写入文件时提示“文件正在由另一进程使用,因此该进程无法访问此文件”的问题

在开发程序的过程中,难免少不了写入错误日志这个关键功能.实现这个功能,可以选择使用第三方日志插件,也可以选择使用数据库,还可以自己写个简单的方法把错误信息记录到日志文件. 选择最后一种方法实现的时候,若对文件操作与线程同步不熟悉,问题就有可能出现了,因为同一个文件并不允许多个线程同时写入,否则会提示“文件正在由另一进程使用,因此该进程无法访问此文件”. 这是文件的并发写入问题,就需要用到线程同步.而微软也给进程同步提供了一些相关的类可以达到这样的目的,本文使用到的 System.Threadin

C#学习笔记---线程同步:互斥量、信号量、读写锁、条件变量

http://www.cnblogs.com/maxupeng/archive/2011/07/21/2112282.html 一.互斥量(mutex) 互斥量本质上是一把锁,在访问共享资源前对互斥量进行加锁,在访问完成后释放互斥量上的锁. 对互斥量进行加锁以后,任何其它试图再次对互斥量加锁的线程将会被阻塞直到当前线程释放该互斥锁.如果释放互斥锁时有多个线程阻塞,所有在该互斥锁上的阻塞线程都会变成可运行状态,第一个变为运行状态的线程可以对互斥量加锁,其它线程将会看到互斥锁依然被锁住,只能回去再次

Linux多线程实践(6) --Posix读写锁解决读者写者问题

Posix读写锁 int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr); int pthread_rwlock_destroy(pthread_rwlock_t *rwlock); int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock); int pthread_rwlock_wrlock(pthre

WINDOWS 同步(Interlocked,InterlockedExchangeAdd,Slim读/写锁,WaitForSingleObject,CreateWaitableTimer等等)

NOTE0 在以下两种基本情况下,线程之间需要相互通信: 需要让多个线程同时访问一个共享资源,同时不能破坏资源的完整性: 一个线程需要通知其它线程某项任务已经完成 1.原子访问:Interlocked系列函数 http://hi.baidu.com/microsoftxiao/blog/item/a6411546296bc90c6a63e561.html该文章不错.    所谓原子访问,指的是一个线程在访问某个资源的同时能够保证没有其他线程会在同一时刻访问同一资源.     我们需要有一种方法能