1
package demo5;

class Process extends Thread {

static int counter = 0;

public static  synchronized void increment() { counter++; }

public void run() {
    for (int i = 0; i < 1000000; i++)
    {
        increment();
    }
    System.out.println("Done.");
  }
}

public class App {

public static void main(String[] args) throws InterruptedException {
    Process p1 = new Process();
    Process p2 = new Process();
    p1.start();
    p2.start();

    p1.join();
    p2.join();

    System.out.println("Value of count is :" + p1.counter);

}

}

如果我将增量​​函数声明为非静态函数,则最后计数器的值不会是 200 万。

另一方面,当增量方法定义为静态时,它可以正常工作。

据我所知,所有 Process 对象只有一个增量函数..那么为什么我必须将其声明为静态方法..?

谢谢

4

2 回答 2

7

将其声明为静态将导致synchronizedProcess.class 实例上的锁定。所以所有运行的线程都会阻塞在increment方法内的对象上。删除静态将导致每个线程仅阻塞 Thread 实例(在您的情况下有两个)。

因此,您的counter变量正在并行递增,并且正如多次指出的那样,int 递增不是线程安全的。

As far as I know there will be only ONE increment function for all the Process objects

Process 类有一个增量函数,但同步是在 Object 而不是方法上完成的,例如:

class Process{
     public synchronized void increment() { counter++; }
}

相当于:

class Process{
     public void increment() { 
           synchronized(this){
                  counter++; 
            }
}

编辑:回答Rouki的问题。

class Process{
     public static synchronized void increment() { counter++; }
}

相当于

class Process{
     public void increment() { 
           synchronized(Process.class){
                  counter++; 
            }
}
于 2013-04-09T14:46:11.733 回答
1

您可能希望用AtomicInteger计数器替换您的 int 计数器 - 这样您可以从方法中删除同步关键字,并且该方法是静态方法还是实例方法无关紧要。

于 2013-04-09T14:47:28.380 回答