通过同步方法获取对象锁

32 浏览
0 Comments

通过同步方法获取对象锁

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

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) {
                e.printStackTrace();
            }
        }
    }
}

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

0
0 Comments

问题的原因是increment()方法是同步的,但是它是Runnable的一部分。另外,计数器变量i是一个局部变量,所以即使没有同步关键字,每个线程也会有自己的i的副本。

解决方法是创建一个名为MyCounter的类,并将其作为参数传递给MultiThr构造函数。MyCounter类有一个私有变量i和相应的getter和setter方法。在increment()方法中,使用synchronized关键字来确保同一时间只有一个线程能够执行该方法。然后,在MultiThr的run()方法中调用increment()方法。

另一种解决方法是使用AtomicInteger而不是MyCounter类。只需确保将同一个AtomicInteger实例传递给每个线程即可。

下面是修复后的代码示例:

class MyCounter {   
    private int i;
    public MyCounter () {
        i = 0;
    }
    public int getCounter() {
        return i;
    }
    public synchronized void increment() {
        i++;
    }
}
public class MultiThr implements Runnable {
    private MyCounter counter;
    
    public MultiThr(MyCounter counter) {
        this.counter = counter;
    }
    
    public void run() {  
        increment();
    }
    
    public void increment() {
        for(int i=0; i<10; i++) {
            counter.increment();
            System.out.println(counter.getCounter());
            try {
                Thread.sleep(400);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }
    
    public static void main(String[] args) {
        MyCounter counter = new MyCounter();
        
        for(int i = 0; i < 5; i++) {
           new Thread(new MultiThr(counter)).start();
        }
    }
}

以上代码中,我们创建了一个MyCounter实例作为计数器,并将其传递给每个MultiThr线程。每个线程都会调用increment()方法来递增计数器,并打印出当前计数器的值。通过在increment()方法上添加synchronized关键字,我们确保了每个线程在执行该方法时都会获取对象锁,从而避免了多个线程同时修改计数器的问题。

0
0 Comments

问题的原因是使用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();
        }
    }
    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) {}
            }
        }
    }
}

以上代码通过创建一个静态的共享对象lock,并在increment方法中使用synchronized关键字锁定这个共享对象,实现了多个MultiThr对象之间的同步。

0