我试图找到Clojure所谓的STM和Haskell中实现的STM之间的差异.除了实际的语言语义差异外,我有点困惑,因为Rich Hickey在演讲中说Clojure的STM实现与其他任何东西都有很大不同,但我不理解除语言选择之外的差异.
haskell language-comparisons transactional-memory clojure stm
总是提到的软件事务存储器的主要优点之一是可组合性和模块性.可以组合不同的片段以产生更大的组分.在基于锁的程序中,通常情况并非如此.
我正在寻找一个用实际代码说明这一点的简单示例.我更喜欢Clojure中的一个例子,但Haskell也很好.如果该示例还展示了一些无法轻松编写的基于锁的代码,则会获得奖励积分.
有一个新的实验功能(可能是C++ 20),它是"同步块".该块提供了一段代码的全局锁定.以下是cppreference的示例.
#include <iostream>
#include <vector>
#include <thread>
int f()
{
static int i = 0;
synchronized {
std::cout << i << " -> ";
++i;
std::cout << i << '\n';
return i;
}
}
int main()
{
std::vector<std::thread> v(10);
for(auto& t: v)
t = std::thread([]{ for(int n = 0; n < 10; ++n) f(); });
for(auto& t: v)
t.join();
}
Run Code Online (Sandbox Code Playgroud)
我觉得这是多余的.上面的一个synchronized块和这个之间有什么区别:
std::mutex m;
int f()
{
static int i = 0;
std::lock_guard<std::mutex> lg(m);
std::cout << i << …Run Code Online (Sandbox Code Playgroud) 在阅读Anandtech的'Haswell TSX'(转换内存屏障)之后,我立刻想知道CLR/JVM是否能够在C#/ Java/Scala/F#中使用这些用于高度并行的应用程序(C#Rx/TPL/TFD).
我有两个MVar(好吧是一个MVar和一个Chan).我需要从Chan中取出并处理它们,直到另一个MVar不再为空.我理想的解决方案就像UNIX select函数,我传入一个(可能是空的)MVar列表和线程块直到其中一个已满,然后它返回完整的MVar.尽量尝试我可以想到除了用isEmptyMVar重复轮询每个MVar之前没办法做到这一点,直到我弄错.这似乎效率低下.
一个不同的想法是使用throwTo,但它会中断线程中发生的事情,我需要以原子方式完成处理Chan的工作.
我正在打字的最后一个想法是为每个MVar创建一个新的forkIO,它试图读取它的MVar然后用自己的实例填充一个新创建的MVar.然后原始线程可以阻止该MVar.Haskell线程是否足够便宜,可以运行那么多?
这只是一个假设情景来说明我的问题.假设它们之间共享两个线程和一个TVar.在一个线程中有一个原子块来读取TVar并需要10秒才能完成.在另一个线程中是一个原子块,每秒修改一次TVar.第一个原子块是否会完成?当然它会一直回到开头,因为日志永远处于不一致的状态?
据我所知,实现软件事务内存有几种不同的算法(这是一个非常活跃的研究领域).我在哪里可以找到(不必深入研究源代码)在不同语言和库中使用,特别是在Clojure和Haskell(GHC)中?
我很困惑,因为从阅读维基页面看起来好像只有一个checkValidate并提交加载和存储系统.解决同步问题的目的是什么?它是构建在当前硬件之上的软件编程事物,还是通过ISA实现的硬件实现?每个(HW/SW)实现之间有什么区别?
谢谢.
我正在检查英特尔的"whatif"网站及其事务内存编译器(每个线程必须进行原子提交或回滚系统的内存,就像数据库一样).
这似乎是替换锁和互斥锁的一种有前途的方法,但我找不到很多推荐.这里有人有任何意见吗?
考虑以下Erlang代码:
-module(testit).
-export([testit/0]).
testit() ->
Pid = spawn(fun testit_proc/0),
Pid ! final,
Pid ! one,
Pid ! two,
io:format("Root finished~n").
testit_proc() ->
receive
one -> io:format("One~n");
two -> io:format("Two~n")
end,
receive
one -> io:format("One~n");
two -> io:format("Two~n")
end,
receive
one -> io:format("One~n");
two -> io:format("Two~n");
final -> io:format("Final~n")
end,
io:format("Spawn finished~n").
Run Code Online (Sandbox Code Playgroud)
输出是:
Root finished
One
Two
Final
Spawn finished
Run Code Online (Sandbox Code Playgroud)
final由于先前的接收模式与该消息不匹配,因此消息的处理基本上被推迟到最后一个接收块.
你如何使用Haskell的TChan做到这一点?