我试图理解并发性与并行性。
我的理解是,当线程依赖于共享状态时,并发性具有竞争条件。例如,如果N个线程同时从共享输入数组弹出并推送到共享输出数组,则存在输出数组将包含重复项的风险。
我知道Ruby解释器是为防止这种行为而设计的,但从概念上讲,我是否正确理解可能性仍存在,如果需要完全原子性,还应采取额外的预防措施?
我试图创建一个显示竞争条件但无法做到的示例。我想知道是否有一些简单的代码来创建竞争条件以显示并发的限制(vs并行性,据我所知是原子的)。
这是尝试 - 这需要大约4秒钟才能运行,并在我的i5处理器上使用大约25%的CPU。没有多少记忆。
module AtomicityTestWithConcurrentThreadsAndGlobalVariables
# parameters
Thread_count = 10_000
Method_calls_per_thread = 10
Global_in_count = Thread_count * Method_calls_per_thread
# global stores
Global_in = 1.upto(Global_in_count).to_a
Global_out = []
# base method
def base_method
Global_out.push Global_in.pop
end
# threads
def n_threads(n, &blk)
n.times.map { Thread.new &blk }
end
# consistency check
def consistency_check
"uniq length: #{Global_out.uniq.length}, total length: #{Global_out.length}"
end
end
# init
if __FILE__ == $0
include AtomicityTestWithConcurrentThreadsAndGlobalVariables
n_threads(Thread_count) do
Method_calls_per_thread.times { base_method }
end.each &:join
puts consistency_check
end
如果我以错误的方式思考这件事,请告诉我。可以预期多个线程以原子方式共享全局状态,因此尝试查找竞争条件毫无意义吗?
另外一些奇怪的是,ruby 1.8.7比ruby 2.3.0更快。
> rbenv global 1.8.7-p370
> time ruby test.rb
uniq length: 100000, total length: 100000
0.18user 0.01system 0:00.24elapsed 81%CPU (0avgtext+0avgdata 21100maxresident)k
0inputs+0outputs (0major+10495minor)pagefaults 0swaps
13:00:34, taken:36, load:1.53, /home/max/Documents
> rbenv global 2.3.0
> time ruby test.rb
uniq length: 100000, total length: 100000
1.72user 0.38system 0:02.28elapsed 92%CPU (0avgtext+0avgdata 74680maxresident)k
0inputs+0outputs (0major+54022minor)pagefaults 0swaps
13:00:41, load:1.64, /home/max/Documents
它采用0.01秒系统,1.8.7和0.38,2.3.0