require 'benchmark'
def f1
puts "sleep 3 seconds in f1\n"
sleep 3
end
def f2
puts "sleep 2 seconds in f2\n"
sleep 2
end
Benchmark.bm do |b|
b.report do
f1
f2
end
end
##
## user system total real
## sleep 3 seconds in f1
## sleep 2 seconds in f2
## 0.000000 0.000000 0.000000 ( 5.009620)
上述代码很简单,用 sleep 模拟耗时的操作.顺序执行时候的消耗时间. 2、并行执行
模拟多线程时的操作
# 接上述代码
Benchmark.bm do |b|
b.report do
threads = []
threads << Thread.new { f1 }
threads << Thread.new { f2 }
threads.each(&:join)
end
end
##
## user system total real
## sleep 3 seconds in f1
## sleep 2 seconds in f2
## 0.000000 0.000000 0.000000 ( 3.005115)
def thread_test
time = Time.now
threads = 3.times.map do
Thread.new do
sleep 3
end
end
puts "不用等3秒就可以看到我:#{Time.now - time}"
threads.map(&:join)
puts "现在需要等3秒才可以看到我:#{Time.now - time}"
end
test
## 不用等3秒就可以看到我:8.6e-05
## 现在需要等3秒才可以看到我:3.003699
require 'benchmark'
def multiple_threads
count = 0
threads = 4.times.map do
Thread.new do
2500000.times { count += 1}
end
end
threads.map(&:join)
end
def single_threads
time = Time.now
count = 0
Thread.new do
10000000.times { count += 1}
end.join
end
Benchmark.bm do |b|
b.report { multiple_threads }
b.report { single_threads }
end
## user system total real
## 0.600000 0.010000 0.610000 ( 0.607230)
## 0.610000 0.000000 0.610000 ( 0.623237)
require 'benchmark'
require 'net/http'
# 模拟网络请求
def multiple_threads
uri = URI("http://www.baidu.com")
threads = 4.times.map do
Thread.new do
25.times { Net::HTTP.get(uri) }
end
end
threads.map(&:join)
end
def single_threads
uri = URI("http://www.baidu.com")
Thread.new do
100.times { Net::HTTP.get(uri) }
end.join
end
Benchmark.bm do |b|
b.report { multiple_threads }
b.report { single_threads }
end
user system total real
0.240000 0.110000 0.350000 ( 3.659640)
0.270000 0.120000 0.390000 ( 14.167703)
在网络请求时程序发生了阻塞,而这些阻塞在Ruby的运行下是可以并行的,所以在耗时上大大缩短了. GIL 的思考
那么,既然有了这个GIL锁的存在,是否意味着我们的代码就是线程安全了呢?
很遗憾不是的,GIL 在ruby 执行中会某一些工作点时切换到另一个工作线程去,如果共享了一些类变量时就有可能踩坑.
那么, GIL 在 ruby代码的执行中什么时候会切换到另外一个线程去工作呢? 有几个明确的工作点: