2013-02-27 2 views
4

Ruby MRI 1.8.7에서 파일 쓰기가 완전히 스레드 안전하다고 생각됩니다.Ruby MRI 1.8.7 - 파일 쓰기 스레드 안전

예 1 - 흠 결과 :

File.open("test.txt", "a") { |f| 
    threads = [] 
    1_000_000.times do |n| 
    threads << Thread.new do 
     f << "#{n}content\n" 
    end 
    end 
    threads.each { |t| t.join } 
} 

예 2 - 흠없는 결과 (하지만 느린) :

threads = [] 
100_000.times do |n| 
    threads << Thread.new do 
    File.open("test2.txt", "a") { |f| 
     f << "#{n}content\n" 
    } 
    end 
end 
threads.each { |t| t.join } 

그래서, 내가 동시성 문제에 직면 시나리오를 재구성하지 수, 수 당신?

누군가 내가 왜 뮤텍스를 사용해야하는지 설명해 주시면 감사하겠습니다.

편집 :

def complicated(n) 
    n.to_s(36).to_a.pack("m").strip * 100 
end 

items = (1..100_000).to_a 

threads = [] 
10_000.times do |thread| 
    threads << Thread.new do 
    while item = items.pop 

     sleep(rand(100)/1000.0) 
     File.open("test3.txt", "a") { |f| 
     f << "#{item} --- #{complicated(item)}\n" 
     } 

    end 
    end 
end 
threads.each { |t| t.join } 

답변

3

내가 중 오류가 발생 할 수 없습니다 : 여기에 완벽하게 잘 작동하고 동시성 문제를 표시하지 않는 다른 더 복잡한 예입니다.

여기에 파일 잠금이 실행 중일 수 있습니다. 같은 파일에 쓸 여러 스레드하고자하는 경우, 그들은 모두 그렇게처럼 같은 파일 객체를 사용한다 :

threads = [] 
File.open("test.txt", "a") do |fp| 
    500.times do |time| 
    threads << Thread.new do 
     fp.puts("#{time}: 1") 
     sleep(rand(100)/100.0) 
     fp.puts("#{time}: 2") 
    end 
    end 
end 

threads.each{ |thread| thread.join } 
GIL은 아마이 예에서는 실제 스레드 버그에서 당신을 저장,하지만 난 것이다

진짜 쓰레드를 사용하는 JRuby에서 일어날 일과 정확히 같은 시간에 일어날 수있는 두 번의 쓰기 작업은 확실하지 않습니다. 실제 쓰레드가있는 다른 루비 엔진에서도 마찬가지입니다.

자물쇠가있는 코드를 보호해야하는 문제에 관해서는 사용하고있는 Ruby 엔진에 의존하고 싶거나, "잘 작동해야하는"솔루션을 코딩하고 싶다면 동시성 문제로부터 당신을 구할 수있는 기능을 내장하고 있는지 여부에 관계없이 모든 Ruby 엔진.

또 다른 질문은 운영 체제 및/또는 파일 시스템이 파일 잠금이있는 스레드 버그에서 사용자를 저장하고 있는지, 그리고 코드가 운영 체제 및/또는 파일 시스템과 독립적이어야한다는 것입니다. 즉, 파일 시스템 잠금에 의존하여 파일 열기 및 쓰기가 운영 체제 및/또는 파일 시스템에 의해 올바르게 동기화되고 있는지 확인하십시오.

저는 루비 엔진, 운영 체제 또는 파일 시스템에 상관없이 코드가 작동하도록 보장하기 위해 좋은 연습처럼 보일 것입니다. 시스템 대부분의 현대 Ruby 엔진, 운영 체제 및 파일 시스템에 이러한 기능이 내장되어 있지만 누군가 다른 사람이 코드를 사용하게됩니다.

+0

소리가 좋지만 잠금 기능을 사용할 때 단점이 있습니까? (성능?) –

+0

이 벤치 마크를 실행하면 Mutex 및 모니터를 사용하여 10 개의 스레드 (1 밀리 총 잠금)에서 100,000 개의 잠금이 MRI에서 0.28 및 0.72 초로 벤치 마크됩니다 내 노트북의 i7 3740QM CPU를 탑재 한 JRuby 1.7.3에서 1.9.3 및 2.13과 5.13 초. 잠금 장치가 적어지기 때문에 성능 손실이 최소화됩니다. – kaspernj

+0

감사합니다. –