2013-04-07 39 views
1

刚开始尝试使用线程,我在想:是否有一种情况使用多个Mutex有意义?是否有任何理由拥有多个全球可访问的互斥体?

我知道Mutex#synchronize用于锁定值,防止竞争条件。我使用它有点像这样:

# class variable 
@semaphore = Mutex.new 

# in thread in method 
self.class.semaphore.synchronize{ x += 1 } 

这是一个很好的方法来锁定?

回答

2

TL; DR

这里有一个经验法则:一定要使用一个互斥体为每个组的变量。例如,对一个数组使用一个互斥体,并将它总是一起使用的元素的计数器。如果两个不同的对象(或对象组)在逻辑上可以在不同的时间由两个不同的线程使用,并且不会破坏您的程序,请为它们提供不同的互斥锁。

把这个情况跟一个互斥体:

$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 

(低用户因为睡眠SYS)

这里的带有两个互斥体的版本:

$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

当然,这是有意义的,如果你有两个对象,,其中的每一个可以独立地使用。如果thread1想要独占访问A,并且thread2想独占访问B,则thread1和thread2不需要彼此等待。所以A有一个信号量和B有一个不同的信号量。不过要小心!你可以得到死锁时,比方说,线程1具有一个并等待收购而线程2具有并等待收购一个

有很多材料可以覆盖共享资源,死锁等等。

相关问题