Random sınıfı iş parçacığı güvenli midir?


110

RandomBirden çok iş parçacığı arasında sınıfın bir örneğini paylaşmak geçerli midir? Ve nextInt(int)özellikle birden çok iş parçacığından aramak ?


@Bala R, hayır, C # 'ın Random nesnesinden değil, Java'dan bahsediyoruz.
Buhake Sindi

ayy. üzgünüm o kısmı kaçırdım.
Bala R

Çok iş parçacıklı bir ortamda sayılar elde etmek için Random'ı kullanmak size kötü sonuçlar verebilir. Belki de önemli değildir, ancak bazı simülasyonlar yapıyorsanız bunu bilmek iyidir.
Maxence SCHMITT

14
Diğer okuyucular için: 1.7 adlı yeni bir sınıf var java.util.concurrent.ThreadLocalRandom.
Jin Kwon

Yanıtlar:


66

Birden çok iş parçacığı tarafından kullanıldığında rasgele sayılar üretmeye devam etmesi açısından iş parçacığı güvenlidir.

Sun / Oracle JVM uygulaması, iş parçacıkları arasında tutarlılığı iyileştirmek için çekirdek olarak senkronize edilmiş ve AtomicLong kullanır. Ancak dokümantasyondaki tüm platformlarda garanti edilmiyor gibi görünüyor.

Özellikle aranacak sırayı belirleyemediğiniz için programınızı böyle bir garanti gerektirecek nextInt()şekilde yazmazdım.


69
Java 7 belgelerine bir garanti eklenmiştir: "java.util.Random örnekleri iş parçacıkları güvenlidir." docs.oracle.com/javase/7/docs/api/java/util/Random.html
Matt R


8

Belgelere göre Math.random () , birden çok iş parçacığı tarafından kullanım için güvenli olduğunu garanti eder. Ancak Random sınıfı bunu yapmaz. O zaman bunu kendiniz senkronize etmeniz gerektiğini varsayıyorum.


7

Evet, Random iş parçacığı açısından güvenlidir. nextInt()yöntem korumalı çağrıları next(int)kullanan yöntem AtomicLong seed, nextseed(uzun atom) bir sonraki tohum üretmek için. AtomicLongtohum üretiminde iplik güvenliği için kullanılır.


6

Söylendiği gibi, bu iş parçacığı tasarrufu, ancak bu makaleyejava.util.concurrent.ThreadLocalRandom göre kullanmak akıllıca olabilir (bağlantı ölü). ThreadLocalRandom ayrıca Random'ın bir alt sınıfıdır, bu nedenle geriye dönük olarak uyumludur.

Ürün farklı Rastgele sınıfların sonuçları profilleme karşılaştırıldı bağladığını: java.util.Random, java.util.concurrent.ThreadLocalRandom ve java.lang.ThreadLocal<java.util.Random>. Sonuçlar, ThreadLocalRandom kullanımının en yüksek performanslı olduğunu, bunu ThreadLocal ve en kötü performans gösteren Random'ın izlediğini gösterdi.


4

Birden fazla iş parçacığının hepsinin aynı Random'ı kullanmaması için hiçbir sebep yok. Bununla birlikte, sınıf açıkça iş parçacığı güvenli olmadığından ve tohum aracılığıyla sözde rasgele sayıların bir dizisini koruduğundan. Birden çok iş parçacığı aynı rasgele sayı ile bitebilir. Her iş parçacığı için birden çok Rastgele oluşturmak ve bunları farklı şekilde tohumlamak daha iyi olacaktır.

DÜZENLE : Sun uygulamasının AtomicLong kullandığını yeni fark ettim, bu yüzden sanırım bu İş Parçacığı için güvenli (Peter Lawrey (+1) tarafından da belirtildiği gibi).

EDIT2 : OpenJDK da tohum AtomicLong kullanır. Başkalarının da söylediği gibi buna güvenmek hala iyi değil.


3

Random'ın atomik değişkenleri kullandığını varsaymadan problemi şu şekilde ele aldım. currentTime * thread idGelecekte bir süre eşitse yine de rastgele çarpışabilir , ancak bu benim ihtiyaçlarım için yeterince nadirdir. Çarpışma olasılığından gerçekten kaçınmak için, her isteğinizin benzersiz bir saat zaman damgası beklemesini sağlayabilirsiniz.

/**
 * Thread-specific random number generators. Each is seeded with the thread
 * ID, so the sequence of pseudo-random numbers are unique between threads.
 */
private static ThreadLocal<Random> random = new ThreadLocal<Random>() {
    @Override
    protected Random initialValue() {
        return new Random(
            System.currentTimeMillis() *
            Thread.currentThread().getId());
    }
};

Yukarı! S: (24*60*60*1000)Kısmen önemli mi?
Jin Kwon

1
Evet, bu kirli bir düzeltmeydi. (24*60*60*1000)Kimliğine sahip bir iplik böylece oldu 12en xxxxxxxxxx045milisaniye bir iş parçacığı aynı seribaşı alamadım 22de xxxxxxxxxx035milisaniye. Ancak iş parçacığı kimliklerinin artımlı olduğunu varsaymak için iyi bir nedenim yok ve yarın bugün olduğundan daha rastgele zamanlarda ileti dizileri oluşturduğumu düşünmek için iyi bir neden yok. Şimdi alg'ı basitleştirdim ve eksikliği belirlemek için açıklamayı güncelledim.
Ryan

0

RandomSınıf birden çok iş parçacığı kullanılmak üzere bir örneği için ayarlanmamış. Tabii ki, bunu yaptıysanız, muhtemelen tahmin edilemez ve rastgele sayılara yaklaşma olasılığınızı artıracaksınız . Ancak sözde rastgele bir üretici olduğu için neden bir örneği paylaşmanız gerektiğini anlayamıyorum. Daha spesifik bir gereklilik var mı?

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.