-1

在此测试线程代码中的代码中,一个线程调用了两个方法addToTotal()countPrimes()但只有前者被标记为同步。

执行时防止交错countPrimes()的原因。countPrimes()i、min、max、count 等使用的变量不也是共享资源吗?那么isPrime()which is called bycountPrimes()呢?

   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 i, min, max,count`使用的变量不也是共享资源吗?

不,它们是当前线程的本地;即到其run()方法调用正在进行的线程。没有其他东西共享它们。

那么isPrime()which is called bycountPrimes()呢?

同样的交易。它只使用局部变量,因此不需要同步。

于 2013-02-17T13:30:08.880 回答
0

synchronized 关键字只是获取某个对象的监视器。如果另一个线程已经拥有监视器,它将必须等待该线程完成,然后才能获取它并继续。任何在公共对象上同步的代码都不能同时运行,因为在任何给定时间只有一个线程可以获取该对象上的监视器。在使用方法的情况下,监视器是隐式的。对于非静态方法,它是调用它的实例,对于静态方法,它是调用它的类型的类。

这是一个可能的原因,但它几乎不能准确指示何时使用关键字。

为了回答这个问题,我想说,只要您不希望两个线程同时执行基于公共监视器的关键部分,您就可以使用同步。您需要这个的情况很多,并且充斥着太多的陷阱和例外,无法完全解释。

您不能通过同步来阻止对整个班级的访问。您可以使每个方法同步,但这仍然不是一回事。另外,它只阻止其他线程在同一监视器上同步时访问关键部分。

于 2013-02-17T07:09:37.037 回答