2012-09-28 48 views
0

比方說,我們要測試數據庫被鎖定..Rails的線程測試分貝鎖定

$transaction = Thread.new { 
    Rails.logger.debug 'transaction process start' 
    Inventory.transaction do 
     inventory.lock! 
     Thread.stop 
     inventory.units_available=99 
     inventory.save 
    end 
    } 
    $race_condition = Thread.new { 
    Rails.logger.debug 'race_condition process start' 
    config = ActiveRecord::Base.configurations[Rails.env].symbolize_keys 
    config[:flags] = 65536 | 131072 | Mysql2::Client::FOUND_ROWS 
    begin 
     connection = Mysql2::Client.new(config) 

     $transaction.run 
     $transaction.join 
    rescue NoMethodError 
    ensure 
     connection.close if connection 
    end 
    } 
    Rails.logger.debug 'main process start' 
    $transaction.join 
    Rails.logger.debug 'main process after transaction.join' 
    sleep 0.1 while $transaction.status!='sleep' 
    Rails.logger.debug 'main process after sleep' 
    $race_condition.join 
    Rails.logger.debug 'main process after race_condition.join' 

從理論上講,我認爲它會做的交易線索,然後等待(使用Thread.stop) ,那麼主進程會看到它正在休眠,並啓動競態條件線程(當實際工作時它將嘗試更改鎖定表中的數據)。然後競爭條件在完成後繼續交易線程。

有什麼奇怪的是跟蹤

main process start 
transaction process start 
race_condition process start 

從即將的NodeJS,好像線程不是完全按照用戶友好的..但是,必須有完成這件事的方式。

是否有更簡單的方法來鎖定數據庫,然後嘗試使用不同的線程更改它?

+0

見我的答案和評分,如果它幫助!乾杯:) – uday

回答

0

對於任何資源,使之成爲「互斥」,則需要使用互斥類,並使用一個同步方法,使資源被鎖定當一個線程使用它們。你必須做這樣的事情:

semaphore = Mutex.new

,並使用它的線程實例內。

$transaction = Thread.new { 
    semaphore.synchronize{ 
    # Do whatever you want with the *your shared resource* 
    } 
} 

這樣可以防止任何死鎖。

希望這會有所幫助。

0

Thread.new自動啓動線程。但這並不意味着它正在執行。 這取決於運營系統,Ruby或JRuby,多少個核心,等

在你的榜樣主線程運行,直到 $ transaction.join, 才把您的交易線程啓動,只是偶然。 它仍然運行Thread.stop,然後你的'$ race_condition'線程開始,因爲其他都被阻塞(它可能已經開始)

這樣就解釋了你的日誌。

你有兩個$ transaction.join
他們等到線程退出,但一個線程只能退出一次...... 我不知道是什麼,然後會發生,也許第二個電話永遠等待。

對於您的測試,您需要某種顯式同步,以便我們的race_thread在transaction_thread處於事務中間時準確寫入。你可以通過Mutex來做到這一點,但更好的做法是傳遞某種消息。下面的博客文章可能有幫助:

http://www.engineyard.com/blog/2011/a-modern-guide-to-threads/