线程编程中锁和原子操作之间的关系

问题描述 投票:2回答:1

是否使用原子操作实现了所有锁?在一些书中,它说“一个锁需要几个原子操作”。我认为原子操作和锁是不同的东西。但似乎我错了。锁和原子操作之间的关系是什么?

multithreading locking atomic
1个回答
1
投票

锁和原子锁是一种保护机制,可以对受锁保护的某些数据执行复杂的线程不安全操作。 Atomic operations是永远不能仅在中途观察的操作,如果多个线程同时访问相同的变量,则不会中断(注意在C ++中,执行原子操作的变量也称为原子)。锁是使用原子操作实现的抽象概念。

如何使用互斥锁/锁定mutex是执行锁定的标准方法:互斥锁始终保护与之关联的一些变量。它被锁定或解锁,并且一次只有一个线程可以锁定它。当互斥锁被锁定时,线程可以对其受保护的变量执行线程不安全的操作,并且保证没有其他线程可以干扰或观察持有锁的线程所做的部分更改。线程完成修改变量后,它可以解锁互斥锁,以便其他线程现在可以访问受保护的变量(通过锁定互斥锁本身)。

请注意,只要线程想要以任何方式访问任何受保护的变量,它就需要锁定相关的互斥锁。否则,不再保证线程不会干扰彼此的工作。

锁是如何实现的?据我所知,锁/互斥锁总是使用原子操作实现。一个这样的操作是atomic exchange:它允许你从变量中读取一个值,并以原子方式向它写一个新值,因此没有其他线程可以干扰这个过程或者在中途完成它。使用原子bool(true = LOCKED,false = UNLOCKED)实现互斥锁,并通过执行以下操作来执行锁定:

while(mutex.locked.exchange(LOCKED) == LOCKED);

这总是将互斥锁设置为LOCKED,并读取先前的值,如果它是UNLOCKED,则结束。在这种情况下,我们是唯一一个将互斥锁从UNLOCKED设置为LOCKED的线程。

解锁非常简单:mutex.locked = UNLOCKED;这只是将互斥锁设置为UNLOCKED,然后可以被其他线程再次锁定。

注意为了简单起见,我确实省略了memory ordering,它是原子的一个方面,它处理一个线程所做的更改对其他线程可见的顺序(与某些内存顺序一样,可能会以与它们不同的顺序观察到更改)制作完成后,多个线程甚至可能会看到不一致订单的变化。内存排序非常复杂。

结论作为一般经验法则,除非你真的知道你在做什么,否则你应该总是使用互斥锁和锁,而不是原子。虽然互斥体速度较慢,但​​它们已经足够复杂,并且更容易正确使用。它们会自动处理所做更改的可见性,因此您的程序变得更容易理解和编写。

© www.soinside.com 2019 - 2024. All rights reserved.