- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
以下是一个简化的C程序,该程序演示了我在使用intel cpu上内置的compare和swap的GNU来实现并发堆栈时遇到的问题。我花了一段时间来了解正在发生的事情,但是现在我知道这完全在原子比较和交换所提供的保证之内。
当节点从堆栈中弹出,修改然后放回堆栈时,修改后的值可能会成为堆栈的新头,从而破坏它。 test_get中的注释描述了导致这种情况的事件的顺序。
有什么方法可以可靠地多次使用同一节点和同一堆栈?这是一个夸张的示例,但是即使将未修改的节点返回给gHead也会泄漏其他节点。该数据结构的初衷是重复使用相同的节点。
typedef struct test_node {
struct test_node *next;
void *data;
} *test_node_p;
test_node_p gHead = NULL;
unsigned gThreadsDone = 0;
void test_put( test_node_p inMemory ) {
test_node_p scratch;
do {
scratch = gHead;
inMemory->next = scratch;
} while ( !__sync_bool_compare_and_swap( &gHead , scratch , inMemory ) );
}
test_node_p test_get( void ) {
test_node_p result;
test_node_p scratch;
do {
result = gHead;
if ( NULL == result ) break;
// other thread acquires result, modifies next
scratch = result->next; // scratch is 0xDEFACED...
// other thread returns result to gHead
} while ( !__sync_bool_compare_and_swap( &gHead , result , scratch ) );
// this thread corrupts gHead with 0xDEFACED... value
if ( NULL == result ) {
result = (test_node_p)malloc( sizeof(struct test_node) );
}
return result;
}
void *memory_entry( void *in ) {
test_node_p node;
int index , count = 1000;
for ( index = 0 ; index < count ; ++index ) {
node = test_get();
*(uint64_t *)(node) |= 0xDEFACED000000000ULL;
test_put( node );
}
__sync_add_and_fetch(&gThreadsDone,1);
return NULL;
}
void main() {
unsigned index , count = 8;
pthread_t thread;
gThreadsDone = 0;
for ( index = 0 ; index < count ; ++index ) {
pthread_create( &thread , NULL , memory_entry , NULL );
pthread_detach( thread );
}
while ( __sync_add_and_fetch(&gThreadsDone,0) < count ) {}
}
test_get
中的点,它们的
result
值相同,但不是
NULL
。然后,将发生以下顺序:
result
返回
test_get
result
的内容
result
,获取放置在其中的任何线程A
result
结尾并调用
test_put
test_put
中交换,将结果放回
gHead
test_get
中交换并通过
gHead
result
。
result
返回
test_get
result
的内容
result
,从而在
scratch
中获得有效值
test_put
并成功
test_put
并成功将
result
放回
gHead
test_get
中交换并通过
gHead
最佳答案
(我正在放弃以前的答案。)
问题是您没有自动读取gHead
和gHead->next
的机制,但是实现无锁堆栈需要这种机制。由于您打算无论如何都忙循环来处理比较和交换冲突,因此可以使用自旋锁的等效项:
void lock_get () {
while (!_sync_bool_compare_and_swap(&gGetLock, 0, 1)) {}
}
void unlock_get () {
unlock_get_success = _sync_bool_compare_and_swap(&gGetLock, 1, 0);
assert(unlock_get_success);
}
test_get()
中的循环可以被
lock_get()
和
unlock_get()
包围。
test_get()
的CAS循环只是一个与
test_put()
竞争的线程。 Jens对CAS循环的实现似乎更干净。
lock_get();
result = __sync_val_compare_and_swap(&gHead, 0, 0);
while ((oldval = result)) {
result = __sync_val_compare_and_swap(&gHead, result, result->next);
if (oldval == result) break;
}
unlock_get();
关于c - 如何防止通过原子比较和交换实现的并发lifo堆栈中的损坏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17248148/
我怎样才能使它进入后进先出队列?有什么简单的方法吗?这是先进先出队列中的 FIFO-> fifo。 using namespace std; int main(){ queue q;
我需要一个支持后进先出 (LIFO) 的 .NET。 有吗?如果有多个,什么是最好的? (我打算将 Form 对象放入其中。) 有什么建议? (注意:集合需要在 Compact Framework 上
我正在准备期中考试,我需要帮助解决这个问题: 假设在 LIFO 堆栈上执行混合的入栈和出栈操作序列。插入按顺序插入数字 0 到 9;弹出窗口打印出返回值。以下哪一个输出序列可能发生?选择所有可能的。
为什么我的 java 堆栈在打印时不遵循 LIFO 原则? import java.util.*; class StackTrace { public static void main(Str
有没有办法让 RabbitMQ 队列像堆栈一样工作,即客户端获取队列中发布的最后一条消息(后进先出)而不是第一条消息?或者使用客户端可以设置的时间戳使其成为优先级队列? RabbitMQ 确实支持优先
对于简单的同步 LIFO,我应该使用什么数据结构?我正在使用 Android Java 1.6。 Java 集合的问题在于存在数百万个略有不同的类和接口(interface)。 最佳答案 标准怎么样S
如何添加 int 值,然后迭代堆栈以获得 LIFO 顺序? 7 和 1 相加返回 7 和 1。 public void calculate_10to99() { Stack romanN
在 FixedThreadPoolExecutor 的以下实现中,使用 LIFO 有序等待线程列表寻找有效的信号量或锁,以尽量减少缓存和页面丢失。 . 最佳答案 使用LIFO数据结构,使线程优先级根据
有没有办法以 LIFO 方式显示数据库中的数据.. 默认以先进先出的方式显示数据 使用 id,timestamp 我们可以以 desc,asc 格式显示数据... 但是 没有任何自动递增字段,我们可以
我想要一个数据结构,固定大小的 LIFO,后进先出。已经存在了吗? 编辑:抱歉,我想要的是 LIFO 而不是 FIFO。 我检查了http://docs.python.org/library/queu
我正在寻找一种基本上是有界堆栈的数据结构。 如果我声明堆栈最多可以容纳 3 个项目,并且我将另一个项目压入,弹出最旧的项目。 最佳答案 您将能够使用双端队列 ( http://en.wikipedia
我正在 Java 的 Collections 框架中寻找 LIFO 结构(堆栈),但没有任何成功。基本上我想要一个非常简单的堆栈;我的完美选择是 Deque,但我使用的是 Java 1.5。 我不想在
我需要设计一个具有以下约束的“优先队列堆栈”数据结构: pop() 和 deleteMin() 在平均情况下以 O(log(n)) 运行。 push(x) 和 getMin() 的平均运行时间为 O(
尝试使用 LIFO(后进先出)概念将最后五个搜索保存在 cookie 中。当搜索六个查询时,它将替换最后一个。我们怎样才能做到这一点。我尝试了这段代码,但它只保存一个值。 function s
假设我有一个 data.table,其中每行由两个向量组成: “预减法”向量。 “减法后”向量。 减法前是最左半列,减法后是最右列,末尾带有后缀“prm”。 例如: #Sample Data set.
我正在学习 F# 代理 (MailboxProcessor)。 我正在处理一个相当不寻常的问题。 我有一个代理 (dataSource),它是流数据源。数据必须由一组代理 (dataProcessor
目前,我在集成流程中使用队列 channel ,但它使用 FIFO 提取方式。有没有办法将其更改为 LIFO? 另外,有没有办法根据属性从队列中删除消息? 我怀疑我需要使用 PriorityChann
已关闭。此问题需要 debugging details 。目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and the
如何使用 Javascript 中的正则表达式对匹配事件创建 LIFO 缓冲区? 这是一个例子: 输入: 4 Mål Vålerenga, 1 - 0 Torgeir Børven. Målgiv
我正在学习 Java 类(class),现在我陷入了一个可能非常明显和清晰的问题,但我在互联网上找不到任何答案,所以我决定来这里亲自问你们。 所以.. JOpitionPane 显示 LIFO(后进先
我是一名优秀的程序员,十分优秀!