Linux 锁小结

/* 未完待续 */

锁就是一个变量,因此在使用前要声明一种类型的锁变量。这个锁变量保存了锁在某一时刻的状态,可用或占用等。

互斥锁

  • pthread_mutex_init(&lock, NULL)    动态初始化互斥锁;
  • phtread_mutex_destory()  销毁互斥锁;
  • pthread_mutex_lock(&lock)  加锁
  • pthread_mutex_unlock(&lock) 释放互斥锁

如果在线程A调用pthread_mutex_lock()函数时,没有其他线程持有该锁,则线程A获取该锁并进入临界区;

如果另一个线程B持有该锁,线程A尝试获取该锁不会从这个调用返回,直到获取到锁(意味着线程B释放了锁)。

2. 条件变量

条件变量是利用线程间共享的全局变量进行同步的一种机制,主要包括两个动作:一个线程等待"条件变量的条件成立"而挂起;另一个线程使"条件成立"(给出条件成立信号)。为了防止竞争,条件变量的使用总是和一个互斥锁结合在一起。

  • 静态初始化条件变量

pthread_cond_t = PTHREAD_COND_INITIALIZER

也可也采用动态初始化的方法,调用pthread_cond_init(),对应的释放函数为pthread_cond_destory()

要使用条件变量,必须要持有该锁才能调用如下函数:

  • pthread_cond_wait(&cond,&lock)   使线程进入休眠状态(睡眠时释放锁,唤醒时加锁)
  • pthrad_cond_signal(&cond) 激活等待列表中的线程

3. 信号量

信号量是一个整数值的对象

int sem_init (sem_t *sem, int pshared, unsigned int value);

这个函数的作用是对由sem指定的信号量进行初始化,设置好它的共享选项,并指定一个整数类型的初始值。pshared参数控制着信号量的类型。Value为信号量的初始值。

int sem_destroy (sem_t *sem)对应的去初始化函数

int sem_post(sem_t * sem);

用来增加信号量的值。当有线程阻塞在这个信号量上时,调用这个函数会使其中的一个线程不在阻塞,选择机制同样是由线程的调度策略决定的

函数的作用是给信号量的值加上一个“1”,它是一个“原子操作”---即同时对同一个信号量做加“1”操作的两个线程是不会冲突的。

int sem_wait(sem_t * sem);

被用来阻塞当前线程直到信号量sem的值大于0,解除阻塞后将sem的值减一,表明公共资源经使用后减少

函数也是一个原子操作,它的作用是从信号量的值减去一个“1”,但它永远会先等待该信号量为一个非零值才开始做减法。也就是说,如果你对一个值为2的信号量调用sem_wait(),线程将会继续执行,介信号量的值将减到1。如果对一个值为0的信号量调用sem_wait(),这个函数就会地等待直到有其它线程增加了这个值使它不再是0为止。如果有两个线程都在sem_wait()中等待同一个信号量变成非零值,那么当它被第三个线程增加一个“1”时,等待线程中只有一个能够对信号量做减法并继续执行,另一个还将处于等待状态。

#include "stdio.h"
#include "pthread.h"
#include "semaphore.h"

sem_t g_sem;

void* fun1(void *arg)
{
	printf("thread 1 start\n");

	sem_wait(&g_sem);   
	printf("thread 1 sem_wait 1\n");

	sem_wait(&g_sem);
	printf("thread 1 sem_wait 2\n");

       return;
}
void* fun2(void *arg)
{
	printf("thread 2 start\n");

	sem_post(&g_sem);
	printf("thread 2 sem_post\n");

      return;
}

int main(void)
{
    pthread_t pthread1;
    pthread_t pthread2;
    int res = 0;
     
    /* 信号量的初始值为1 */
    sem_init(&g_sem, 0, 1);

    res = pthread_create(&pthread1, NULL, fun1, NULL);
    sleep(1);
    pthread_create(&pthread1, NULL, fun2, NULL);
    sleep(1);

     sem_destroy(&g_sem);

    return 0;
}

运行结果

thread 1 start
thread 1 sem_wait 1
thread 2 start
thread 2 sem_post
thread 1 sem_wait 2

说明:信号量初始值为1,进入线程1后,第一次执行sem_wait,信号量减一,第二次执行sem_wait时,当前信号量值为0,此时线程1阻塞。知道线程2,执行sem_post,信号量加1,激活被阻塞的线程1

Ref: https://blog.csdn.net/linfeng999/article/details/6291824

4. 读写锁

多个读者可以并发读,写着只能有一个写者

typedef struct _rwlock_t
{
    sem_t lock;
    sem_t writelock;
    int  readers;
}rwlock_t;

void rwlock_int(rwlock_t *rw)
{
    rw->readers = 0;
    sem_init(&rw->lock, 0, 1);
    sem_init(&rw->writelock, 0, 1);
}

void rwlock_acquire_readlock(rwlock_t *rw)
{
    sem_wait(&rw->lock);
    rw->readers++;
    if(rw->readers == 1)
        sem_wait(&rw->writelock);  // first reader acquires writelock
    sem_post(&rw->lock);
}

void rwlock_release_readlock(rwlock_t *rw)
{
    sem_wait(&rw->lock);
    rw->readers--;
    if(rw->readers == 0)
       sem_post(&rw->writelock);   // last reader releases writelock
    sem_post(&rw->lock);
}

void rwlock_acquire_writelock(rwlock_t *rw)
{
    sem_wait(&rw->writelock);
}

void rwlock_release_writelock(rwlock_t *rw)
{
    sem_post(&rw->writelock);
}

5. 自旋锁

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值