我对以下代码示例有疑问(摘自:http://www.albahari.com/threading/part4.aspx#_NonBlockingSynch)
class Foo
{
int _answer;
bool _complete;
void A()
{
_answer = 123;
Thread.MemoryBarrier(); // Barrier 1
_complete = true;
Thread.MemoryBarrier(); // Barrier 2
}
void B()
{
Thread.MemoryBarrier(); // Barrier 3
if (_complete)
{
Thread.MemoryBarrier(); // Barrier 4
Console.WriteLine (_answer);
}
}
}
Run Code Online (Sandbox Code Playgroud)
接下来是以下解释:
"障碍1和障碍4阻止这个例子编写"0".障碍2和3提供了新鲜度保证:他们确保如果B在A之后运行,则读取_complete将评估为真."
我理解如何使用记忆障碍影响指令的记录,但这提到的"新鲜保证"是什么?
在本文后面,还使用了以下示例:
static void Main()
{
bool complete = false;
var t = new Thread (() =>
{
bool toggle = false;
while (!complete)
{ …Run Code Online (Sandbox Code Playgroud) 最近发现了这样的java-concurrency面试任务:
使用两种方法编写简单的无锁Stack:push和pop.
我做了专注:
import java.util.concurrent.atomic.AtomicInteger;
public class Stack {
private AtomicInteger count = new AtomicInteger(-1);
private Object[] data = new Object[1000];
public void push(Object o) {
int c = count.incrementAndGet();
data[c] = o;
}
public Object pop() {
Object top;
int c;
while (true) {
c = count.get();
if (c == -1) return null;
top = data[c];
if (count.compareAndSet(c, c-1))
return top;
}
}
}
Run Code Online (Sandbox Code Playgroud)
是否与预期的方法类似?或者"无锁堆栈"意味着什么不同?请帮助一个java面试新手.
因此,无锁是指尽管某些线程可能会饥饿,但您可以保证整个系统取得进展。因此基于 CAS 的实现将提供这种保证。
那么无阻塞是指如果所有其他线程都挂起,则保证一个线程完成。
你能举一个非无锁的无阻塞算法的简单例子吗?
谢谢!
编辑:这不是任何允许在 post() 中互斥锁定的问题的重复。请仔细阅读,我需要一个无锁帖子()!如果您没有真正的答案,请不要标记此重复项。
信号量(如在 Linux 中)是一个有用的构建块,但在 C++ 标准中没有找到,在 boost(目前)中也没有。我主要讨论的是抢占式调度程序中单个进程的线程之间的信号量。
我对它们的非阻塞(即无锁)特别感兴趣,除非它实际上需要阻塞。也就是说,post() 和 try_wait() 应该始终是无锁的。如果 wait() 调用强烈发生在足够的 post() 返回之后,那么 wait() 调用应该是无锁的。此外,阻塞 wait() 应该被调度程序阻塞而不是自旋锁定。如果我还想要一个带有超时的 wait_for 该怎么办 - 它会使实现进一步复杂化,同时仍然避免饥饿?
信号量不在标准中是否有原因?
Edit3:所以,我不知道有一个针对标准 P0514R4 的提案可以准确处理这些问题,并且除了专门添加 std::semaphore 之外,还可以解决此处提出的所有问题。http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0514r4.pdf
而且boost没有这些。具体来说,进程间的进程是自旋锁定的。
哪些库支持类似的东西?
是否可以通过 windows api 和其他广泛的系统来实现它?
编辑:不可能使用原子+互斥体+条件变量来实现无锁 - 您要么必须在发布中阻塞,要么在等待中旋转。如果您想要无锁的 post(),则不能在 post() 中锁定互斥体。我想在可能抢占式的调度程序上运行,并且我不希望 post() 被其他获取互斥锁并被抢占的线程阻塞。那么,这不是像C++0x has no semaphores 这样的问题的重复吗?如何同步线程?
edit2:下面的示例实现只是为了演示使用atomics+mutex+condvar可以完成的最佳操作,据我所知。post() 和 wait() 执行一次无锁比较交换,并且只有在必须时,它们才会锁定互斥锁。
然而 post() 不是无锁的。更糟糕的是,它可能会被锁定互斥锁并被抢占的 wait() 阻塞。
为了简单起见,我只实现了 post_one() 和 wait_one_for(Duration),而不是 post(int) 和 wait_for(int,Duration)。另外,我假设标准没有承诺无虚假唤醒。
class semaphore //provides acquire release memory ordering for the …Run Code Online (Sandbox Code Playgroud) 更新:在C或C++中可用的所有Linux发行版增量函数都有线程安全,无锁且可用吗?
标题几乎传达了所有相关信息,但这里是一个最小的重复:
#include <atomic>
#include <cstdio>
#include <memory>
int main() {
auto ptr = std::make_shared<int>(0);
bool is_lockless = std::atomic_is_lock_free(&ptr);
printf("shared_ptr is lockless: %d\n", is_lockless);
}
Run Code Online (Sandbox Code Playgroud)
使用以下编译器选项进行编译会产生无锁shared_ptr实现:
g++ -std=c++11 -march=native main.cpp
Run Code Online (Sandbox Code Playgroud)
虽然这不是:
g++ -std=c++11 -march=native -pthread main.cpp
Run Code Online (Sandbox Code Playgroud)
GCCversion :( 5.3.0在Linux上,使用libstdc++),在多台机器上进行测试,这些机器应具有必要的原子指令才能使其工作.
有没有办法强制实现无锁实现(我需要无锁版本,无论性能如何)?
我有一个编写者必须以相当高的频率增加变量,还有一个或多个读者以较低的频率访问该变量。
写入由外部中断触发。
由于我需要高速写入,因此我不想使用互斥体或其他昂贵的锁定机制。
我想出的方法是在写入后复制该值。读者现在可以将原件与副本进行比较。如果它们相等,则变量的内容有效。
这是我在 C++ 中的实现
template<typename T>
class SafeValue
{
private:
volatile T _value;
volatile T _valueCheck;
public:
void setValue(T newValue)
{
_value = newValue;
_valueCheck = _value;
}
T getValue()
{
volatile T value;
volatile T valueCheck;
do
{
valueCheck = _valueCheck;
value = _value;
} while(value != valueCheck);
return value;
}
}
Run Code Online (Sandbox Code Playgroud)
其背后的想法是在读取时检测数据争用,并在发生时重试。但是,我不知道这是否永远有效。我在网上没有找到任何关于这种方法的信息,因此我的问题是:
当我的方法与单个作者和多个读者一起使用时有什么问题吗?
我已经知道高写作频率可能会导致读者饥饿。还有其他我需要警惕的不良影响吗?难道这根本就不是线程安全的吗?
编辑1:
我的目标系统是 ARM Cortex-A15。
T应该能够成为至少任何原始整型。
编辑2:
std::atomic读者和作家网站上的速度太慢。我在我的系统上对其进行了基准测试。与未受保护的原始操作相比,写入速度大约慢 30 倍,读取速度大约慢 50 倍。
使用std::atomic而不是互斥锁的全部意义在于:
当使用互斥表“模拟”操作的原子性时:
那么为什么对原子 CPU 操作的这种糟糕的模拟值得呢?中非无锁回退机制的用例是std::atomic什么?
嘿伙计们,
我正在阅读这些所谓的非阻塞技术,但我几乎没有怀疑:
1)使用原子操作执行无锁操作,现在这些原子操作是什么?我的意思是在一定程度上他们还需要锁定吗?那么这种无锁方法是否只能让我们以更精细的粒度锁定?
2)他们说非阻塞列表,现在应该是一个非阻塞列表:如果同一个插入的多个线程出现,只有一个会成功,另一个会做其他工作吗?,但是如果除了插入一个节点,其他线程别无选择,那么它是如何进行非阻塞的呢?它不会被阻止,直到前一个完成?
3)在java中,它们如何进行原子操作?他们不是这样做的, synchronized boolean .....
因为他们正在获取锁定即同步部分,它是如何无锁的?4)CAS通常用于实现原子操作.那么cas不允许在同一个对象上只发生一个操作,并停止(阻止)那些想要在同一个对象上操作的人吗?很抱歉这么多疑惑......请澄清......
编辑
当我有更新结构时会发生什么?它也受硬件支持吗?没有权利,那么语言是否会在某种程度上获取锁定以使这些结构操作成为原子?
关于JAVA:有AtomicReference和AtomicReferenceFieldUpdater类,它为对象(结构或任何类型的对象)提供更新,所以我们可以在性能方面比较它们,我的意思是速度吗?在tern中都使用了使用Native类的Unsafe类.
假设我们Container维护了一组int值,并为每个值指示了该值是否有效.无效值被认为是INT_MAX.最初,所有值都无效.第一次访问值时,将其设置为INT_MAX并将其标志设置为有效.
struct Container {
int& operator[](int i) {
if (!isValid[i]) {
values[i] = INT_MAX; // (*)
isValid[i] = true; // (**)
}
return values[i];
}
std::vector<int> values;
std::vector<bool> isValid;
};
Run Code Online (Sandbox Code Playgroud)
现在,另一个线程同时读取容器值:
// This member is allowed to overestimate value i, but it must not underestimate it.
int Container::get(int i) {
return isValid[i] ? values[i] : INT_MAX;
}
Run Code Online (Sandbox Code Playgroud)
这是完全合法的代码,但是它行是至关重要的(*),并(**)在给定的顺序执行.
-O3,也不想使用volatile.