刚刚开始尝试使用线程,我想知道:是否存在使用多个Mutex有意义的情况?
我知道Mutex#synchronize用于锁定值,防止竞争条件。我使用它有点像这样:
# class variable
@semaphore = Mutex.new
# in thread in method
self.class.semaphore.synchronize{ x += 1 }
这是一种接近锁定的好方法吗?
答案 0 :(得分:2)
这是一条经验法则:始终为每组变量使用一个互斥锁。例如,对一个数组使用一个互斥锁,并使用一直使用的元素的计数器。如果两个不同的对象(或对象组)可以在不同时间由两个不同的线程在逻辑上使用而不会破坏您的程序,请为它们提供不同的互斥锁。
使用一个互斥锁来处理这种情况:
$counter1 = 0
$counter2 = 0
$mutex = Mutex.new #Just one mutex
threads = []
threads << Thread.new do
$mutex.syncronize do
3.times do |i|
sleep(1) #some calculation
$counter1 += i
end
end
end
threads << Thread.new do
$mutex.syncronize do
3.times do |i|
sleep(1) #some calculation
$counter2 += i * 3
end
end
end
threads.each {|t| t.join}
以下是时间值:
real 0m6.019s
user 0m0.012s
sys 0m0.004s
(由于睡眠原因导致用户和系统不足)
这是一个包含两个互斥锁的版本:
$counter1 = 0
$counter2 = 0
$mutex1 = Mutex.new
$mutex2 = Mutex.new
threads = []
threads << Thread.new do
$mutex1.syncronize do
3.times do |i|
sleep(1) #some calculation
$counter1 += i
end
end
end
threads << Thread.new do
$mutex2.syncronize do
3.times do |i|
sleep(1) #some calculation
$counter2 += i * 3
end
end
end
threads.each {|t| t.join}
时间值:
real 0m3.021s
user 0m0.020s
sys 0m0.004s
这是速度的x2增加,因为我们删除了迫使两个线程相互等待的锁定条件,在第一种情况下有效地消除了线程的任何好处。显然,每个变量的一个互斥量是效率的大幅提升。
答案 1 :(得分:1)
当然,如果您有两个对象 A 和 B ,每个对象都可以独立使用,这是有道理的。如果thread1想要对 A 进行独占访问,并且thread2想要对 B 进行独占访问,则thread1和thread2不需要彼此等待。所以 A 有一个信号量, B 有一个不同的信号量。不过要小心!例如,当thread1具有 A 并等待获取 B 而thread2具有 B 并等待获取 A <时,您可能会遇到死锁/强>
有很多材料涉及共享资源,死锁等。