![]() |
1
27
这里没有人在Java中提供这个算法的正确/安全的实现。我不确定John W的解决方案应该如何工作,因为它丢失了一些片段(即线程局部变量的声明和对其数组“原始”中应包含的内容的解释)。
Chapter 17 of the Java Language Specification 解释Java内存模型。特别感兴趣的是 Section 17.4.5 ,它描述了 以前发生过 秩序。在一个线程中思考是很容易的。考虑一下这段代码:
每个人都会同意在这段代码的末尾
因为它们都出现在同一个线程中,jls说这些读和写都保证显示出这种顺序:每个操作 n 上面(因为操作在一个线程中)与所有操作都有一个“发生在前”关系 米 , 米 gt; n . 但是不同的线程呢? 对于正常的字段访问,在线程之间建立关系之前不会发生这种情况。 这意味着线程A可以增加共享变量,线程B可以读取该变量,但是 看不到新值 . 在JVM中的程序执行过程中,线程A的写入的传播可能已经被重新排序,以便在线程B读取之后发生。
实际上,线程A可以写入变量
我们如何解决这个问题?对于正常的现场访问,
与同步
如果线程A希望线程B看到它的写入操作,则是比以前发生的情况更强的条件,并且由于以前发生的情况是可传递的。
在加布里埃尔的解决方案中,我们看到了这样一个模式:一个写入发生在
不幸的是,while循环的条件是向后的:为了保证线程不会看到
考虑到这个修正,剩下的大部分解决方案都是可以的:在关键部分,我们不关心数据的过时,因为,好吧,我们在关键部分!最后还有一个缺陷:可运行集
那么我们该如何修复它呢?只需添加另一个写入
由于我们重新排序了while循环,另一个线程将保证看到
不用说,没有度量标准
吨
在评论中,这个方法是脆弱的,有人可能会过来改变一些东西,并巧妙地破坏正确性。只是声明数组
如果您希望您的代码清晰简洁,请保持原样并进行更改。
|
![]() |
2
5
除非您对彼得森的算法有特定的需求(当使用Java这样的高级语言时,这将是奇怪的),我建议您查看内置在语言中的同步设施。 例如,您可以在本书中找到关于“比赛条件和 “互斥”在Java中有用: http://java.sun.com/developer/Books/performance2/chap3.pdf 在粒子中:
|
![]() |
3
4
我自己在网上找不到,所以我决定试着写:
请随时发表评论,我们将不胜感激:) |
![]() |
4
3
你真的应该看看《多处理器编程艺术》这本书。他详细介绍了不同的锁实现(旋转和阻塞)。他还介绍了其他不同类型的并发算法(例如跳过列表)。这是他关于彼得森锁算法的书中的一个片段
|
![]() |
5
0
虽然不是paterson算法,但atomicBoolean和atomic*类使用无锁繁忙循环的方法来更新共享数据。它们可能符合您的要求。 |
![]() |
a a · 为什么在这个可重入锁示例中需要引用计数? 2 年前 |
![]() |
Grant · goroutines有高空闲唤醒电话 3 年前 |
![]() |
hoaz · 如何安全地清理并发映射 6 年前 |
![]() |
Alanpatchi · int基元类型的volatile声明 7 年前 |