使用同步方法获取对象锁定

时间:2017-09-12 17:27:21

标签: java multithreading

下面的代码没有给出同步输出。

public class MultiThr implements Runnable{

public static void main(String[] args) {

    for(int i = 0;i < 5;i++){
        new Thread(new MultiThr()).start();
    }
}

@Override
public void run() {

    increment();
}

public synchronized void increment(){
    for(int i=0;i<10;i++){
        System.out.println(i);
        try {
            Thread.sleep(400);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
}

有人可以解释一下如何在 increment()方法上获取对象锁吗?

2 个答案:

答案 0 :(得分:0)

synchronized关键字的这种用法导致该方法获取对正在调用该方法的对象的锁定。由于您有5个MultiThr个对象,因此5个不同的对象被锁定。

有很多选项可以解决这个问题,例如你可以创建一个在所有MultiThr个对象之间共享的对象:

public class MultiThr implements Runnable{
    private static final Object lock = new Object();

    public static void main(String[] args) {
        for(int i = 0;i < 5;i++){
            new Thread(new MultiThr()).start();
        }
    }

    @Override
    public void run() {
        increment();
    }

    public void increment(){
        synchronized (lock) {
            for(int i=0;i<10;i++){
                System.out.println(i);
                try {
                    Thread.sleep(400);
                } catch (InterruptedException e) {}
            }
        }
    }
}

答案 1 :(得分:-1)

您的increment()方法同步。您的问题是它是Runnable的一部分。更多的是,你的计数器变量i是一个局部变量,因此即使没有synchronized关键字,每个线程也会拥有它自己的i副本。 我建议你做的是创建一个类MyConter,如:

class MyCounter {   

    private int i;

    public MyCounter () {
        i = 0;
    }

    public int getCounter() {
        return i;
    }

    public void increment() {
        i++;
    }
}

然后将它作为参数传递给MultiThr构造函数:

public class MultiThr implements Runnable{

    private MyCounter counter;

    public MultiThr(MyCounter counter)  {
        this.counter = counter;
    }

    @Override
    public void run() {  
        increment();
    }

    public synchronized void increment(){
        for(int i=0;i<10;i++){
            counter.increment();
            System.out.println(counter.getCounter());
            try {
                Thread.sleep(400);
            } catch (InterruptedException e) {
                // Do not do just e.printStackTrace()
                Thread.currentThread().interrupt()
            }
        }
    }

    public static void main(String[] args) {
        for(int i = 0;i < 5;i++){
           new Thread(new MultiThr()).start();
        }
    }
}

或者您可以使用AtomicInteger而不是MyCounter,只需确保将相同的实例传递给每个线程。