-1

このテスト スレッド コードから抜粋したこのコードでは、スレッドが 2 つのメソッドaddToTotal()を呼び出しますcountPrimes()が、前者のみが同期とマークされています。

が実行されているときにインターリーブを防止するものcountPrimes()countPrimes()i、min、max、count などで使用される変数も共有リソースではありませんか。そして、isPrime()によって呼び出されるのは何countPrimes()ですか?

   public class ThreadTest2 {

    private static final int START = 3000000;

    private static int total;

    synchronized private static void addToTotal(int x) {
        total = total + x;
        System.out.println(total + " primes found so far.");
    }

    private static class CountPrimesThread extends Thread {
        int count = 0;
        int min, max;
        public CountPrimesThread(int min, int max) {
            this.min = min;
            this.max = max;
        }
        public void run() {
            count = countPrimes(min,max);
            System.out.println("There are " + count + 
                " primes between " + min + " and " + max);
            addToTotal(count);
        }
    }

    private static void countPrimesWithThreads(int numberOfThreads) {
        int increment = START/numberOfThreads;
        System.out.println("\nCounting primes between " + (START+1) + " and " 
            + (2*START) + " using " + numberOfThreads + " threads...\n");
        long startTime = System.currentTimeMillis();
        CountPrimesThread[] worker = new CountPrimesThread[numberOfThreads];
        for (int i = 0; i < numberOfThreads; i++)
            worker[i] = new CountPrimesThread(START+i*increment+1, START+(i+1)*increment );
        total = 0;
        for (int i = 0; i < numberOfThreads; i++)
            worker[i].start();
        for (int i = 0; i < numberOfThreads; i++) {
            while (worker[i].isAlive()) {
                try {
                    worker[i].join();
                } catch (InterruptedException e) {
                }
            }
        }
        long elapsedTime = System.currentTimeMillis() - startTime;
        System.out.println("\nThe number of primes is " + total + ".");
        System.out.println("\nTotal elapsed time:  " + (elapsedTime/1000.0) + " seconds.\n");
    }

    public static void main(String[] args) {
        int processors = Runtime.getRuntime().availableProcessors();
        if (processors == 1)
            System.out.println("Your computer has only 1 available processor.\n");
        else
            System.out.println("Your computer has " + processors + " available processors.\n");
        int numberOfThreads = 0;
        while (numberOfThreads < 1 || numberOfThreads > 5) {
            System.out.print("How many threads do you want to use  (from 1 to 5) ?  ");
            numberOfThreads = TextIO.getlnInt();
            if (numberOfThreads < 1 || numberOfThreads > 5)
                System.out.println("Please enter 1, 2, 3, 4, or 5 !");
        }
        countPrimesWithThreads(numberOfThreads);
    }

    private static int countPrimes(int min, int max) {
        int count = 0;
        for (int i = min; i <= max; i++)
            if (isPrime(i))
                count++;
        return count;
    }

    private static boolean isPrime(int x) {
        int top = (int)Math.sqrt(x);
        for (int i = 2; i <= top; i++)
            if ( x % i == 0 )
                return false;
        return true;
    }
}
4

3 に答える 3

5

countPrimes共有変数にアクセスしないため、同期は必要ありません (引数とローカル変数でのみ機能します)。したがって、同期するものは何もありません。

一方、total変数は複数のスレッドから更新されるため、正確性を確保するためにアクセスを同期する必要があります。

于 2013-02-17T07:08:31.717 に答える
3

countPrimes() が実行されているときにインターリーブを妨げるものは何ですか?

何もない。これを防ぐ必要はありません (以下を参照)。また、必要がないので、インターリーブを防止することは、並列処理を減らすので悪いことです。

countPrimes()like iminmax,count`で使用される変数も共有リソースではありませんか?

いいえ。それらは現在のスレッドに対してローカルです。run()つまり、メソッド呼び出しが進行中のスレッドに。それらを共有するものは他にありません。

そして、isPrime()によって呼び出されるのは何countPrimes()ですか?

同じ取引。ローカル変数のみを使用しているため、同期は必要ありません。

于 2013-02-17T13:30:08.880 に答える
0

synchronized キーワードは、あるオブジェクトのモニターを取得するだけです。別のスレッドが既にモニターを持っている場合は、そのスレッドが終了するまで待ってから取得して続行する必要があります。特定の時点でそのオブジェクトのモニターを取得できるスレッドは 1 つだけであるため、共通オブジェクトで同期するコードは同時に実行できません。メソッドの場合、使用されるモニターは暗黙的です。非静的メソッドの場合は呼び出されたインスタンスであり、静的メソッドの場合は呼び出された型のクラスです。

これは考えられる理由の 1 つですが、キーワードをいつ使用するかを正確に示しているとは言えません。

質問に答えるには、共通のモニターに基づいてクリティカル セクションを同時に実行する 2 つのスレッドが必要ない場合は、同期を使用することをお勧めします。これが必要になる状況は数多くあり、完全に説明するにはあまりにも多くの落とし穴や例外に悩まされています。

同期されたクラス全体へのアクセスを防ぐことはできません。すべてのメソッドを同期させることができますが、それでもまったく同じではありません。さらに、同じモニターで同期するときに、他のスレッドがクリティカル セクションにアクセスするのを防ぐだけです。

于 2013-02-17T07:09:37.037 に答える