标签: lock-free

内存栅栏如何影响数据的"新鲜度"?

我对以下代码示例有疑问(摘自: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)

c# c++ multithreading memory-model lock-free

2
推荐指数
1
解决办法
613
查看次数

简单的无锁堆栈

最近发现了这样的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面试新手.

java stack lock-free

2
推荐指数
1
解决办法
4375
查看次数

非无锁的无阻塞算法的例子是什么?

因此,无锁是指尽管某些线程可能会饥饿,但您可以保证整个系统取得进展。因此基于 CAS 的实现将提供这种保证。

那么无阻塞是指如果所有其他线程都挂起,则保证一个线程完成。

你能举一个非无锁的无阻塞算法的简单例子吗?

谢谢!

concurrency multithreading lock-free

2
推荐指数
1
解决办法
910
查看次数

C++ 信号量(半*无锁*),在哪里可以获得?

编辑:这不是任何允许在 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++ lock-free thread-synchronization c++11

2
推荐指数
1
解决办法
1888
查看次数

线程安全,无锁增量功能?

更新:在C或C++中可用的所有Linux发行版增量函数都有线程安全,无锁且可用吗?

c c++ linux multithreading lock-free

1
推荐指数
3
解决办法
2402
查看次数

链接pthread会禁用无锁的shared_ptr实现

标题几乎传达了所有相关信息,但这里是一个最小的重复:

#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++ atomic lock-free shared-ptr c++11

1
推荐指数
1
解决办法
466
查看次数

快速且无锁的单写入器、多读取器

我有一个编写者必须以相当高的频率增加变量,还有一个或多个读者以较低的频率访问该变量。

写入由外部中断触发。

由于我需要高速写入,因此我不想使用互斥体或其他昂贵的锁定机制。

我想出的方法是在写入后复制该值。读者现在可以将原件与副本进行比较。如果它们相等,则变量的内容有效。

这是我在 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 倍。

c++ multithreading lock-free

1
推荐指数
1
解决办法
2883
查看次数

对于 CPU 无法原子操作的类型, std::atomic 有什么意义?

使用std::atomic而不是互斥锁的全部意义在于:

  1. 更高的多线程代码性能(阅读器之间没有争用);
  2. 发生严重争用时的性能变化较小(重试失败的 RMW 不如失去剩余时间片那么剧烈,因为持有互斥锁的线程已准备好运行但未运行);
  3. 与信号处理程序通信的能力。

当使用互斥表“模拟”操作的原子性时:

  1. 对于只需要一个修改操作的情况,性能充其量与用户互斥锁一样好;当多个操作顺序使用时,将需要进行多次加锁/解锁操作,从而降低代码效率。
  2. 性能将不会比使用显式用户互斥锁更可预测。
  3. 这种“模拟”原子性不能与阻塞其他代码(例如信号处理程序)的代码一起使用。

那么为什么对原子 CPU 操作的这种糟糕的模拟值得呢?中非无锁回退机制的用例是std::atomic什么?

c++ multithreading mutex lock-free stdatomic

1
推荐指数
1
解决办法
254
查看次数

锁定免费的CAS混淆

嘿伙计们,
我正在阅读这些所谓的非阻塞技术,但我几乎没有怀疑:

1)使用原子操作执行无锁操作,现在这些原子操作是什么?我的意思是在一定程度上他们还需要锁定吗?那么这种无锁方法是否只能让我们以更精细的粒度锁定?
2)他们说非阻塞列表,现在应该是一个非阻塞列表:如果同一个插入的多个线程出现,只有一个会成功,另一个会做其他工作吗?,但是如果除了插入一个节点,其他线程别无选择,那么它是如何进行非阻塞的呢?它不会被阻止,直到前一个完成?
3)在java中,它们如何进行原子操作?他们不是这样做的, synchronized boolean ..... 因为他们正在获取锁定即同步部分,它是如何无锁的?4)CAS通常用于实现原子操作.那么cas不允许在同一个对象上只发生一个操作,并停止(阻止)那些想要在同一个对象上操作的人吗?很抱歉这么多疑惑......请澄清......

编辑 当我有更新结构时会发生什么?它也受硬件支持吗?没有权利,那么语言是否会在某种程度上获取锁定以使这些结构操作成为原子?
关于JAVA:有AtomicReference和AtomicReferenceFieldUpdater类,它为对象(结构或任何类型的对象)提供更新,所以我们可以在性能方面比较它们,我的意思是速度吗?在tern中都使用了使用Native类的Unsafe类.

java cas multicore lock-free

0
推荐指数
1
解决办法
1406
查看次数

重新排序操作和无锁数据结构

假设我们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)

这是完全合法的代码,但是它行是至关重要的(*),并(**)在给定的顺序执行.

  1. 在这种情况下,标准是否保证线路按给定顺序执行?至少从单线程的角度来看,线路可以互换,不是吗?
  2. 如果没有,确保订单的最有效方法是什么?这是高性能的代码,所以我不能没有-O3,也不想使用volatile.

c++ gcc lock-free compiler-optimization c++14

0
推荐指数
1
解决办法
94
查看次数