0

我有这个打印计数器的同步方法,我有 4 个线程,所以我希望我的计数器的最终值为 400000,因为我的计数器是一个静态变量。

但是每次我运行我的代码时,它都会给我不同的计数器值。

以下是我的代码:

class MyThread implements Runnable{

    private static int counter=1;
    @Override
    public void run() {
        try {
            this.syncMethod();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    public synchronized void syncMethod() throws InterruptedException{
        for(int i=0;i<100000;i++){
            System.out.println(Thread.currentThread().getName()+" : "+counter++);
        }
    }
}

public class MyController {
    public static void main(String[] args) throws InterruptedException {
        Runnable r1=new MyThread();
        Runnable r2=new MyThread();
        Runnable r3=new MyThread();
        Runnable r4=new MyThread();
        Thread t1;
        Thread t2;
        Thread t3;
        Thread t4;
        t1=new Thread(r1,"Thread 1");
        t2=new Thread(r2,"Thread 2");
        t3=new Thread(r3,"Thread 3");
        t4=new Thread(r4,"Thread 4");

        t2.start();
        t1.start();
        t3.start();
        t4.start();
    }
}
4

3 回答 3

4

变量是static,但你的方法synchronized不是static。这意味着它将获取当前实例上的监视器,并且每个线程都有不同的当前实例。

一个简单的解决方案是也制作该syncMethod方法static;在这种情况下,它将锁定由MyThread该类的所有实例共享的监视器:

public static synchronized void syncMethod()
于 2018-07-02T05:39:30.570 回答
1

Erwin Bolwidt 的回答对解决您的问题是正确的。作为在多个线程中安全地增加静态共享计数器的另一种方法,您可以使用AtomicLong

将其定义为:

private static AtomicLong counter = new AtomicLong();

将其递增为:

counter.getAndIncrement();

最后,得到结果:

counter.get();
于 2018-07-02T05:55:07.793 回答
0

非静态方法中的同步关键字意味着与此方法完全同步:这两个代码严格等效:

public synchronised void dojob(){
     //the job to do 
}

public void dojob(){
     synchronised (this){
     //the job to do 
     }
}

在您的情况下,您的同步方法正在不同的对象(t1、t2、t3 和 t4)上同步,所以不要互相阻止它们。最好的解决方案是你的线程将使用一个公共对象来相互同步。另一点,最好让它的线程回来做这个调用,在这里加入是一个代码,可以用这 2 个修复来做你想做的事情

class MyThread implements Runnable {

    public static class JobDoer {

        public synchronized void syncMethod() throws InterruptedException {
            for (int i = 0; i < 100000; i++) {
                System.out.println(Thread.currentThread().getName() + " : " + counter++);
            }
        }
    }

    private static int counter = 1;

    public MyThread(JobDoer doer) {
        this.doer = doer;
    }

    private JobDoer doer;

    @Override
    public void run() {
        try {
            doer.syncMethod();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        JobDoer doer = new JobDoer();
        Thread t1 = new Thread(new MyThread(doer), "Thread 1");
        Thread t2 = new Thread(new MyThread(doer), "Thread 2");
        Thread t3 = new Thread(new MyThread(doer), "Thread 3");
        Thread t4 = new Thread(new MyThread(doer), "Thread 4");

        t2.start();
        t1.start();
        t3.start();
        t4.start();
        t1.join();
        t2.join();
        t3.join();
        t4.join();
    }
}
于 2018-07-02T06:06:37.603 回答