IDC资讯

质量为本、客户为根、勇于拼搏、务实创新

< 返回IDC资讯列表

linux中各种锁机制使用与区别详解

发布时间:2022-05-31

桂哥网络想和大家分享linux中各种锁机制的使用和区别的详细解释。相信大部分人还是不太了解。因此,我想把这篇文章分享给你参考。希望你看完这篇文章后收获很大。我们一起来看看。

前言:

相信需要了解这些知识的小伙伴们,已经基本理解了流程和线程之间的沟通。比如进程间通信的机制之一:共享内存(此处不详述):多个进程可以同时访问同一个内存。如果对该内存关键区域的访问不是互斥或同步的,则在进程运行中可能会出现一些不可预测的错误和结果。

接下来,我们了解Linux下三种常见的互斥操作——锁。

1.互斥锁(mutex)

读者和作家的特点:。只要一方获取锁,另一方就不能继续获取,然后执行关键段代码。

创建锁:

创建互斥体有两种方式,静态和动态。POSIX定义了一个宏PTHREAD _ MUTEX _ INITIALIZER来静态初始化互斥体。

方法如下:

PTHREAD _ MUTEX _ tmutex=PTHREAD _ MUTEX _ INITIALIZER;在LinuxThreads实现中,pthread_mutex_t是一个结构,而PTHREAD_MUTEX_INITIALIZER是一个结构常量。

在动态模式下,使用pthread_mutex_init()函数初始化互斥体,API定义如下:

int pthread _ mutex _ init(pthread _ mutex _ t * mutex,const pthread _ mutexatr _ t * mutex ATR),其中mutex ATR用于指定mutex属性(见下文),如果为NULL,则使用默认属性。Pthread_mutex_destroy()用于取消一个互斥体,API定义如下:

int pthread _ mutex _ destroy(pthread _ mutex _ t * mutex)锁定操作主要包括锁定pthread_mutex_lock(),解锁pthread_mutex_unlock()和测试锁定pthread_mutex_trylock()。无论哪种锁,都不可能被两个不同的线程锁定,对于普通锁和自适应锁类型,解锁器可以是同一进程中的任意线程;检错锁一定要由储物柜解锁才能生效,否则,EPERM被返回;对于嵌套锁,文档和实现要求一定要由锁柜解锁,但实验结果表明没有这种限制,这种区别还没有得到解释。如果同一个进程中的一个线程被锁定,但没有被解锁,则没有其他线程可以获得该锁。

intpthread _ mutex _ lock(pthread _ mutex _ t * mutex)

intpthread _ mutex _ unlock(pthread _ mutex _ t * mutex)

int pthread _ mutex _ try lock(pthread _ mutex _ t * mutex)pthread _ mutex _ try lock()在语义上类似于pthread_mutex_lock(),只是在锁被占用时返回EBUSY,而不是挂起等待。

例如,在单一模式下,线程安全锁定:

classSingleTon

{

public:

staticSingleTon*getInstance()

{

pthread _ mutex _ lock(mutex);

如果(mpSingle==空)

{

mpSingleTon=newSingleTon();

}

pthread _ mutex _ unlock(mutex);

returnmpSingleTon

}

private:

SingleTon(){ };

~ Singleton(){ pthread _ mutex _ dest troy(mutex,NULL);}

staticpthread _ mutex _ tmutex

staticSingleTon * mpSingleTon

}

PTHREAD _ MUTEX _ tsingleton : Mutex=PTHREAD _ MUTEX _ INITIALIZER;

SingleTon * SingleTon : psisingleton=NULL;优点:

它由一个可以被多个进程共享的内存空间(一个对齐的整数变量)组成;这个整数变量的值可以通过调用汇编语言中CPU提供的原子操作指令来增加或减少,一个进程可以等到那个值变成正数。几乎所有的操作都是在应用空间完成的;只有当操作结果不一致,需要仲裁时,才需要进入操作系统的内核空间执行。这种机制允许锁定原语具有非常高的执行效率:由于大多数操作,

作并不需要在多个进程之间进行仲裁,所以绝大多数操作都可以在应用程序空间执行,而不需要使用(相对高代价的)内核系统调
用。

2.读写锁

特点:读写锁适合于对数据结构的读次数比写次数多得多的情况.因为,读模式锁定时可以共享,以写 模式锁住时意味着独占,所以读写锁又叫共享-独占锁.

初始化和销毁:

intpthread_rwlock_init(pthread_rwlock_t*restrictrwlock,const
pthread_rwlockattr_t*restrictattr);
intpthread_rwlock_destroy(pthread_rwlock_t*rwlock);

成功则返回0,出错则返回错误编号. 同互斥量以上,在释放读写锁占用的内存之前,需要先通过 pthread_rwlock_destroy对读写锁进行清理工作, 释放由init分配的资源.

读和写:

intpthread_rwlock_rdlock(pthread_rwlock_t*rwlock);
intpthread_rwlock_wrlock(pthread_rwlock_t*rwlock);
intpthread_rwlock_unlock(pthread_rwlock_t*rwlock);

成功则返回0,出错则返回错误编号.这3个函数分别实现获取读锁,获取写锁和释放锁的操作.获 取锁的两个函数是阻塞操作,同样,非阻塞的函数为:

intpthread_rwlock_tryrdlock(pthread_rwlock_t*rwlock);
intpthread_rwlock_trywrlock(pthread_rwlock_t*rwlock);

成功则返回0,出错则返回错误编号.非阻塞的获取锁操作,如果可以获取则返回0,否则返回 错误的EBUSY.

3.自旋锁

特点:轮询忙等待。

在单核cpu下不起作用:被自旋锁保护的临界区代码执行时不能进行挂起状态。会造成死锁
自旋锁的初衷就是:在短期间内进行轻量级的锁定。一个被争用的自旋锁使得请求它的线程在等待锁重新可用的期间进行自旋(特别浪费处理器时间),所以自旋锁不应该被持有时间过长。如果需要长时间锁定的话, 最好使用信号量。

API:

以上是“linux中各种锁机制使用与区别详解”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注亿速云行业资讯频道!


TikTok千粉号购买平台:https://tiktokusername.com/