我注意到(读取:发现了一个生产错误)Julia中的不同任务 - 没有自己的工作目录,但是当前目录是共享的。我意识到在操作系统级别这很明显(一个进程有一个工作目录)。
我的问题是第一个 - 是否有任何其他明显或不太明显的全局状态我应该注意(显然是环境变量或任何全局变量)。
第二 - 如果更多地记录或者通过任务抽象来避免 - 抽象中的“任务”,它(理论上)可以拥有它自己的语义,比如回到工作目录。
我们通过从代码中删除任何'cd()'调用解决了产品错误,重点是 - 带有闭包抽象的cd()让我们觉得这可能是安全的。
即:
cd("some_dir") do
# stuff
end
我们已经在Mux个端点使用了这种代码。
我对这个问题的最小再现是
function runme(path)
mkpath(path)
abs_path = realpath(path)
return t = @async begin
cd(abs_path) do
sleep(1)
println(path,"::",(pwd()|>splitdir)[2])
end
end
end
runme("a")
runme("b")
输出:(显然)
a::b
b::b
编辑:(摘要) - 虽然这几乎不是一个问题 - 这应该是可搜索和记录的(因为它可能是同步错误的来源)。
与全局变量的区别(关于'cd()'的状态) - 可以使用let
语句在闭包中捕获变量,而当前目录则不能。虽然这甚至不是特定于编程语言(但是操作系统进程问题) - 我认为语法确实给出了局部性的假象(类似于'with'或'或许多其他设备的python'。
因此,底线是'cd'抽象不应该在任何生产实用程序中使用,除非有一天有办法设置一个处理器'切换回'到Task / block / closure(类似于{ {1}}阻止某种方式)
答案 0 :(得分:1)
我没有明确地意识到内部或特定的实现,这是我个人受过良好教育的猜测,很高兴被一个真正的julia开发者纠正,但我认为这不是任务共享的情况"当前目录"本身,但他们更普遍地分享"州"。您的示例将采用与全局变量相同的方式:
# in testscript.jl
var = 0;
function runme(val)
global var = val+1;
return t = @async begin
sleep(1)
println(val,"::",var);
end
end
runme(1)
runme(3)
# in the REPL session
julia> include("testo.jl");
1::4
3::4
然而,共享(全局)状态是一个功能,而不是一个错误。这与进程(这是julia实现真正并行性的方式)形成对比,后者不共享状态,因此工作者之间的所有通信都需要通过套接字来完成。
虽然人们确实需要小心这一点,但它也非常有用和必要。在这方面,任务(或协同程序)不用于实现并行性或限制性。它们是一种协作式多任务处理的形式,即在同一线程上实现多次运行操作的一种方式;这不是并行性,多个操作一次运行一次,具有适当的调度,由CPU"监督。例如"尝试/捕获"块(显然)使用Tasks实现。
所以,要回答你的第一个问题,是的,你需要了解共享状态,对于第二个问题,不要,在某种程度上你以某种方式访问任务的方式全局状态(当前目录是一个方面)我并不完全确定每个任务应该按照你描述的方式拥有自己的语义;相反,你只需要设计你的任务,使他们考虑到共享国家的事实,并采取相应的行动。
作为第二个例子的另一个例子,考虑两个单独的任务,即产生"需要消耗的输出"。如果依赖于基于全局状态的任一任务的适当消耗,则完全有可能您的任务应该按照设计的共享全局状态进行适当的操作。这是一个微不足道的例子:
d = 0;
function report()
global d;
for i in 1:4
if iseven(d); produce("D is Even\n"); else; produce("D is Odd\n"); end
end
end
task1 = Task( report );
task2 = Task( report );
for i in 1:4
d = i;
consume(task1) |> print;
consume(task2) |> print;
end
D is Odd
D is Odd
D is Even
D is Even
D is Odd
D is Odd
D is Even
D is Even
<子> PS。最新的朱莉娅建筑告诉我&#34;生产&#34;并且&#34;消费&#34;正在被弃用以支持&#34;频道&#34;,但大概就是这一点。