Linux 锁小结

阅读: 评论:0

Linux 锁小结

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 startn");sem_wait(&g_sem);   printf("thread 1 sem_wait 1n");sem_wait(&g_sem);printf("thread 1 sem_wait 2n");return;
}
void* fun2(void *arg)
{printf("thread 2 startn");sem_post(&g_sem);printf("thread 2 sem_postn");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:

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 writelocksem_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 writelocksem_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. 自旋锁

本文发布于:2024-01-31 08:53:29,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170666241227336.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

上一篇:MySQL 进阶 锁
下一篇:java代码块锁
标签:小结   Linux
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23