में डेडलॉक मुझे रूबी के लिए एक सभ्य थ्रेडपूल कार्यान्वयन नहीं मिला, इसलिए मैंने अपना लिखा (आंशिक रूप से यहाँ से कोड पर आधारित: http://snippets.dzone.com/posts/show/3276, लेकिन थ्रेडपूल शट डाउन के लिए प्रतीक्षा/सिग्नल और अन्य कार्यान्वयन में बदल गया। हालांकि कुछ समय बाद (100 धागे होने और 1300 के बारे में कार्यों को प्रबंधित करने) चल रहा है, यह लाइन 25 पर गतिरोध के साथ मर जाता है -। यह वहाँ एक नया काम के लिए इंतजार कर रहा है कोई भी विचार, क्यों यह हो सकता हैथ्रेडपूल
require 'thread'
begin
require 'fastthread'
rescue LoadError
$stderr.puts "Using the ruby-core thread implementation"
end
class ThreadPool
class Worker
def initialize(callback)
@mutex = Mutex.new
@cv = ConditionVariable.new
@callback = callback
@mutex.synchronize {@running = true}
@thread = Thread.new do
while @mutex.synchronize {@running}
block = get_block
if block
block.call
reset_block
# Signal the ThreadPool that this worker is ready for another job
@callback.signal
else
# Wait for a new job
@mutex.synchronize {@cv.wait(@mutex)} # <=== Is this line 25?
end
end
end
end
def name
@thread.inspect
end
def get_block
@mutex.synchronize {@block}
end
def set_block(block)
@mutex.synchronize do
raise RuntimeError, "Thread already busy." if @block
@block = block
# Signal the thread in this class, that there's a job to be done
@cv.signal
end
end
def reset_block
@mutex.synchronize {@block = nil}
end
def busy?
@mutex.synchronize {[email protected]?}
end
def stop
@mutex.synchronize {@running = false}
# Signal the thread not to wait for a new job
@cv.signal
@thread.join
end
end
attr_accessor :max_size
def initialize(max_size = 10)
@max_size = max_size
@workers = []
@mutex = Mutex.new
@cv = ConditionVariable.new
end
def size
@mutex.synchronize {@workers.size}
end
def busy?
@mutex.synchronize {@workers.any? {|w| w.busy?}}
end
def shutdown
@mutex.synchronize {@workers.each {|w| w.stop}}
end
alias :join :shutdown
def process(block=nil,&blk)
block = blk if block_given?
while true
@mutex.synchronize do
worker = get_worker
if worker
return worker.set_block(block)
else
# Wait for a free worker
@cv.wait(@mutex)
end
end
end
end
# Used by workers to report ready status
def signal
@cv.signal
end
private
def get_worker
free_worker || create_worker
end
def free_worker
@workers.each {|w| return w unless w.busy?}; nil
end
def create_worker
return nil if @workers.size >= @max_size
worker = Worker.new(self)
@workers << worker
worker
end
end
1. @workers तक पहुंच को सिंक्रनाइज़ नहीं किया जाना चाहिए? 2. कार्यकर्ता थ्रेड में अभी भी लॉक और अनलॉक करने की आवश्यकता क्यों है? – Roman
कार्यकर्ता तक पहुंच हमेशा एक ही थ्रेड से की जाती है ... इसलिए सिंक्रनाइज़ेशन की आवश्यकता नहीं होती है। कार्यकर्ता धागे में लॉक के लिए, आपको थ्रेड को सुरक्षित रूप से उठाने की आवश्यकता है। – PierreBdR
इसमें अभी भी एक समस्या है - डेडलॉक के लिए एक मौका है - जब कार्यकर्ता धागा स्वयं को कतार में जोड़ता है, तो थ्रेडपूल इसे कतार से ले जा सकता है और कार्य सौंप सकता है। उस मामले में एक संकेत भेजा जाएगा। हालांकि, अगर कार्यकर्ता धागा सीवी पर इंतजार नहीं कर रहा है, तो सिग्नल खो जाएगा। – Roman