标签: compare-and-swap

条件变量是如何实现的?

这让我困惑了很长时间。

给定基本的原子原语(例如比较和交换),我可以了解如何实现自旋锁(我可以从中构建互斥体)。

但是,我不知道如何从中构建条件变量。这是怎么做到的?

mutex conditional-statements compare-and-swap

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

使用CAS进行原子交换(使用gcc sync builtins)

比较和交换函数可以用于原子交换变量吗?我在x86_64 RedHat Linux上通过gcc使用C/C++,特别是__sync builtins.例:

   int x = 0, y = 1; 
   y = __sync_val_compare_and_swap(&x, x, y);
Run Code Online (Sandbox Code Playgroud)

我认为这归结为x是否可以在&x和x之间变化; 例如,如果&x构成一个操作,则x可能会在参数中的&x和x之间进行更改.我想假设上面隐含的比较总是正确的; 我的问题是我是否可以.显然有CAS的bool版本,但是我不能让旧的x写入y.

一个更有用的例子可能是从链表的头部插入或删除(gcc声称支持指针类型,所以假设是elem和head是):

   elem->next = __sync_val_compare_and_swap(&head, head, elem); //always inserts?
   elem = __sync_val_compare_and_swap(&head, head, elem->next); //always removes?
Run Code Online (Sandbox Code Playgroud)

参考:http: //gcc.gnu.org/onlinedocs/gcc/Atomic-Builtins.html

c++ gcc linked-list atomic compare-and-swap

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

Go中的原子比较和交换结构

我想创建一个非阻塞队列包描述使用算法通过马吉德·M. Michael和迈克尔·L.·斯科特并发应用在这里.

这需要使用"sync/atomic"包提供的原子CompareAndSwap .
但是我不确定以下伪代码的Go等价物是什么:

E9:   if CAS(&tail.ptr->next, next, <node, next.count+1>)
Run Code Online (Sandbox Code Playgroud)

其中tailnext类型:

type pointer_t struct {
    ptr   *node_t
    count uint
}
Run Code Online (Sandbox Code Playgroud)

并且node是类型:

type node_t struct {
    value interface{}
    next  pointer_t
}
Run Code Online (Sandbox Code Playgroud)

如果我理解正确,似乎我需要用一个结构(一个指针和一个uint)来做一个CAS .使用atomic-package 可以实现这一点吗?

感谢帮助!

queue struct go compare-and-swap

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

原子比较(不等于)和交换

我想使用原子比较和交换,但不是等于,我想只在内存位置不等于旧值时进行交换.在C中有可能吗?

c multithreading gcc compare-and-swap

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

为什么GCC填充这个位域?

程序在C中使用std = c99,这是在64位机器上.

struct epochs {
    volatile unsigned int epoch    : 1;
    volatile unsigned int pulse    : 1;
    volatile unsigned int active0  : 7;
    volatile unsigned int active1  : 7;
    volatile unsigned int counter0 : 24; 
    volatile unsigned int counter1 : 24; 
};
Run Code Online (Sandbox Code Playgroud)

当我检查sizeof(epochs)它给了我12.

我可以告诉gcc不要通过添加__attribute((packed))来填充它; 所以我可以解决它.但是,我真的想知道为什么要添加4个字节来填充这个64位结构?

这里的主要内容是这个结构需要64位,因为它在64位原子交换操作中一次更新,当然这对12字节值不起作用.

c struct atomic padding compare-and-swap

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

不了解Java原子包中的CAS操作

我正在研究Java书籍中的并发包。我不太了解本书中有关CAS操作的内容。下面的代码示例是counter本书中的线程安全类。

public class Counter{
    private AtomicInteger count = new AtomicInteger();
    public void increment(){
        count.getAndIncrement();    //atomic operation
    }
    ....
}
Run Code Online (Sandbox Code Playgroud)

这是书中所说的。

实际上,即使诸如这样的方法也要getAndIncrement()花费几个步骤来执行。此实现现在是线程安全的,因此称为CAS。CAS代表“比较并交换”。大多数现代CPU都有一组CAS指令。现在正在发生的事情的基本概述如下:

  1. 存储在count中的值将被复制到一个临时变量中。
  2. 临时变量增加。
  3. 将当前计数的值与原始值进行比较。如果未更改,则将旧值替换为新值。

好吧,我明白它关于多个步骤的说法。我不太了解的是枚举步骤中正在发生的事情。

  1. 存储在count中的值将被复制到一个临时变量中。

该临时变量在哪里?它在主存储器中,注册吗?还是特定于CPU体系结构?

  1. 将当前计数的值与原始值进行比较。如果未更改,则将旧值替换为新值。

原始值存储在哪里?不能是临时变量。那个人正在被修改,对吧?我想念什么?

谢谢

java atomicity compare-and-swap

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

Interlocked.Exchange <T>比Interlocked.CompareExchange <T>慢?

在优化程序时,我遇到了一些奇怪的性能结果,这些结果显示在以下BenchmarkDotNet基准测试中:

string _s, _y = "yo";

[Benchmark]
public void Exchange() => Interlocked.Exchange(ref _s, null);

[Benchmark]
public void CompareExchange() => Interlocked.CompareExchange(ref _s, _y, null);
Run Code Online (Sandbox Code Playgroud)

结果如下:

BenchmarkDotNet=v0.10.10, OS=Windows 10 Redstone 3 [1709, Fall Creators Update] (10.0.16299.192)
Processor=Intel Core i7-6700HQ CPU 2.60GHz (Skylake), ProcessorCount=8
Frequency=2531248 Hz, Resolution=395.0620 ns, Timer=TSC
.NET Core SDK=2.1.4
  [Host]     : .NET Core 2.0.5 (Framework 4.6.26020.03), 64bit RyuJIT
  DefaultJob : .NET Core 2.0.5 (Framework 4.6.26020.03), 64bit RyuJIT

          Method |      Mean |     Error |    StdDev |
---------------- |----------:|----------:|----------:|
        Exchange | 20.525 …
Run Code Online (Sandbox Code Playgroud)

.net c# interlocked compare-and-swap .net-core

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

一些特定用例的C ++原子存储顺序

在下一种情况下,我将a atomic<uint64_t>用作计数器,并从5个或更多线程中对其进行递增,并在递增之前使用该值来做出一些决定。

atomic<uint64_t> global_counter;

void thread_funtion(){
    uint64_t local_counter = global_counter.fetch_add(1,std::memory_order_relaxed);
    if(local_counter == 24)
       do_somthing(local_counter);
}
Run Code Online (Sandbox Code Playgroud)

thread_funtion()将由5个不同的线程执行。一旦我知道了,local_counter我的代码就不再关心global_counterthread_funtion()运行时是否再次进行更改(业务逻辑的方式是每次thread_function()调用仅需要一个唯一的递增值)。

std::memory_order_relaxed安全的,在这种情况下使用?

c++ multithreading thread-safety compare-and-swap stdatomic

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

cmpxchg 是否会在失败时写入目标缓存行?如果不是,对于自旋锁来说它比 xchg 更好吗?

我假设简单的自旋锁不会进入操作系统等待这个问题的目的。

我发现简单的自旋锁通常使用lock xchgorlock bts代替 来实现lock cmpxchg

cmpxchg但是如果期望不匹配,是否会避免写入该值?那么失败的尝试不是更便宜吗cmpxchg

或者即使cmpxchg发生故障也会写入数据并使其他核心的缓存线无效?

这个问题类似于什么具体将 x86 缓存行标记为脏 - 任何写入,还是需要显式更改?,但它是特定的cmpxchg,而不是普遍的。

x86 assembly micro-optimization compare-and-swap cpu-cache

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

如何通过将最后一位设置为 1 来“标记”指针?

我正在尝试标记和取消标记指针,以便我可以实现非阻塞链表。我检查过在我的体系结构上从未使用过最后一位,因此我尝试使用更改它来标记/取消标记指针。

我正在尝试执行 OR 将最后一位设置为 1,执行 AND 来取消设置它,执行 AND 来检查它是否设置为 1。问题是,当我对指针执行按位(注释的宏)操作时,我无法取消引用它。即使指针的整数值是正确的,取消引用它也会导致分段错误。

更具体地说,这#define unmark(x) (x & (uintptr_t) 0xfffffffe)就是导致分段错误的原因。如果我不使用它(而是使用它#define unmark(x) x - 1),程序就可以工作。

递增和递减指针似乎有效,但它可能会使解决方案架构变得特定。这是因为在我的架构上,指针总是以 8 结尾,最后一位设置为 0。如果不是这种情况,我的解决方案将不是很可移植。

我知道操作指针可能无论如何都不可移植,但这是该算法所必需的。如果有人知道导致问题的原因,那就太棒了。

这是我用来测试解决方案的代码:

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>

//This produces segfault, for some reason
//#define unmark(x)     (x & (uintptr_t) 0xfffffffe)
//#define mark(x)   (x | (uintptr_t) 0x00000001)
#define is_marked(x)    ((long) x & 0x00000001)

#define mark(x)     x + 1
#define unmark(x)   x - 1

struct Example {
     long x;
     long y;
};

int main() …
Run Code Online (Sandbox Code Playgroud)

c pointers nonblocking bitwise-operators compare-and-swap

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