UNIX环境高级编程笔记(17)- 线程同步-读写锁、条件变量、自旋锁、屏障

 


前言

本章主要介绍线程同步中的读写锁、条件变量、自旋锁、屏障。


 

一、读写锁介绍

读写锁与互斥量类似,不过读写锁允许更高的并行性。互斥量要么是锁住状态,要么是不加锁状态,而且一次只有一个线程对其加锁。读写锁可以有3中状态,读模式的加锁状态,写模式的加锁状态,不加锁状态。一次只有一个线程可以占用写模式的读写锁,但是多个线程可以同时占有读模式写的读写锁。

当读写锁是在写加锁状态时,在这个锁被解锁之前,所有试图对这个锁加锁的线程都会被阻塞。当读写锁在读加锁状态时,所有试图以读模式对它进行加锁的线程都可以得到访问权限,但是任何希望以写模式对此锁进行加锁的线程都会阻塞。

二、读写锁函数

#include <pthread.h>

#include <time.h>

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(pthread_rwlock_t *rwlock);//写锁

int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);//解锁

int pthread_rwlock_timedrdlock(pthread_rwlock_t *restrict rwlock, const struct timespec *restrict tsptr);//带超时的读锁

int pthread_rwlock_timedwrlock(pthread_rwlock_t *restrict rwlock, const struct timespec *restrict tsptr);//带超时的写锁

三、条件变量

条件变量是线程可用的另一种同步机制,条件变量给多个线程提供了一个会合的场所。条件变量与互斥量一起使用,允许线程以无竞争的方式等该特定条件的发生。

#include <pthread.h>

int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr); //初始化

int pthread_cond_destroy(pthread_cond_t *cond);//删除

int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);//等待条件变量为真

int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict tsptr);//等待条件变量为真,增加超时

int pthread_cond_signal(pthread_cond_t *cond);//至少唤醒一个等待改条件的线程

int pthread_cond_broadcast(pthread_cond_t *cond);//唤醒等该改条件的所有线程

四、条件变量例程

代码如下(示例):

void maketimeout(struct timespec *tsp,long minutes)
{
    struct timeval now;

    gettimeofday(&now,NULL);
    tsp->tv_sec = now.tv_sec;
    tsp->tv_nsec = now.tv_usec * 1000;
    
    tsp->tv_sec += minutes * 60;
}
struct msg{
    struct msg *m_next;
    /*...more stuff here...*/
};

struct msg *workq;

pthread_cond_t qready = PTHREAD_COND_INITIALIZER;
pthread_mutex_t qlock = PTHREAD_MUTEX_INITIALIZER;

void process_msg(void)
{
    struct msg *mp;
    for(;;){
        pthread_mutex_lock(&qlock);
        while(workq == NULL)
            pthread_cond_wait(&qready,&qlock);
        mp = workq;
        workq = mp->m_next;
        pthread_mutex_unlock(&qlock);
        /* now process the message mp*/
    }
}
void enqueue_msg(struct msg *mp)
{
    pthread_mutex_lock(&qlock);
    mp->m_next = workq;
    workq = mp;
    pthread_mutex_unlock(&qlock);
    pthread_cond_signal(&qready);
}

五、自旋锁的介绍

自旋锁与互斥量类似,但是它不是通过休眠使进程阻塞,而是在获取锁之前一直处于忙等(自旋)阻塞状态。

自旋锁可以用于一下情况:锁被持有的时间短,而且线程并不希望在重新调度上花费太多的成本。

六、自旋锁函数

#include <pthread.h>

int pthread_spin_init(pthread_spinlock_t *lock, int pshared);

int pthread_spin_destroy(pthread_spinlock_t *lock);

int pthread_spin_lock(pthread_spinlock_t *lock);

int pthread_spin_trylock(pthread_spinlock_t *lock);

int pthread_spin_unlock(pthread_spinlock_t *lock);

七、屏障的介绍

屏障是用户协调多个线程并行工作的同步机制。屏障允许每个线程等待,直到所有的合作线程都达到某一点,然后从该点继续执行。

屏障允许任意数量的线程等待,直到所有线程完成处理工作。所有线程到达屏障后可以接着工作。

八、屏障函数

#include <pthread.h>

int pthread_barrier_init(pthread_barrier_t *restrict barrier, cosnt pthread_barrierattr_t *attr, unsigned int count);//初始化

int pthread_barrier_destroy(pthread_barrier_t *barrier);

int pthread_barrier_wait(pthread_barrier_t *barrier);


总结

本文章主要介绍了线程同步的四种方式:读写锁、条件变量、自旋锁、屏障。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

默默的赶路人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值