无法在java中同步方法

时间:2013-11-24 19:04:34

标签: java multithreading synchronization synchronized

我试图理解java中的线程同步,下面是代码,其中有一个名为Interview的主类。在那个课程中,我正在创建两个对象

public class Interview{

    /**
     * @param args the command line arguments
     * @throws java.lang.InterruptedException
     */
    public static void main(String[] args) throws InterruptedException {
        // TODO code application logic here\
        Race r1=new Race();
        r1.setA(15);
        Thread t1=new Thread(r1, "First thread");
        Race r2=new Race();
        r2.setA(25);

        Thread t2=new Thread(r2, "Second thread");
        t1.start();
        t2.start();
        }
}

还有其他类具有名为Race的run方法,这里是代码

public class Race implements Runnable{
    int a;

    public int getA() {
        return a;
    }

    public void setA(int a) {
        this.a = a;
    }
    @Override
    public void run() {
        try {

                print();



        } catch (InterruptedException ex) {
            Logger.getLogger(Race.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
   public synchronized void print() throws InterruptedException{
       for(int i=1;i<=10;i++){
           System.out.println(a*i);
           Thread.sleep(1000);
       }

   }
}

对于每个对象,我给出不同的a值,然后尝试同步打印方法,但它不起作用。我正在使用的概念是两个尝试同时访问分片资源的线程无法使用synchronized方法。所以在我的情况下,两个线程t1和t2试图同时访问打印方法所以我使用了synchronized关键字和print方法,但结果仍然相同。我想要的是线程t1首先执行i,e。 15 30 45 60 .....然后线程t2,即25 50 75 ......依此类推。 如果我的概念不清楚,请纠正我。

4 个答案:

答案 0 :(得分:2)

您的synchronized方法是一种实例方法。这意味着通过实例本身获得了用于同步的锁。因此,当你的线程运行时,一个锁定r1,另一个锁定r2。因此,它工作正常,这不是你所期待的。

看起来你想在r1和r2之间创建互斥。为此,您的方法需要是静态的,以便通过类对象获得锁定。或者你需要使用一个不同的锁对象,由两个线程共享(完全基于你的例子看起来不必要)。

换句话说,你的线程没有共享同一个对象,因此它们之间没有任何竞争条件。

例如,您可以通过使两个线程使用相同的Race实例或创建两者共享的互斥对象来创建互斥。

像这样:

class Race {
  public void synchronized print(){
    ...
  }
}

Race r = new Race();
Thread t1 = new Thread(r); 
Thread t2 = new Thread(r); //notice both threads share r.

t1.start();
t2.start();

在上面的示例中,两个线程都将尝试在同一对象上运行print方法。这意味着,synchornized关键字正在此处创建互斥模块。当时只有一个线程可以获得对竞赛对象的锁定。

如果您使用两个不同的Race实例,那么创建互斥是没有意义的。由于没有竞争条件,因此没有必要使线程彼此协调。那只会毫无需要地延迟它们。

答案 1 :(得分:1)

规则实际上是两个在同一个对象上同步的方法无法同时运行。

声明为synchronized的非静态方法在其对象上同步,因此每个Race中的print()方法在其自己的Race对象上同步。

您可以声明一个synchronized块,其中包含在共享对象上进行同步的方法体,例如Race.class。

答案 2 :(得分:0)

无法保证首先执行哪个线程。由JVM决定首先启动哪个线程。正如您所说What I want is thread t1 to execute first i,e. 15 30 45 60..... then thread t2 i.e, 25 50 75... and so on,您可以使用join()方法。它将确保只有在加入它的线程完成后才会执行其他线程。有关更多信息,请参阅this

答案 3 :(得分:0)

public class Race implements Runnable {
    private final Object lock;

    public Race(Object lock) {
        this.lock = lock;
    }

    @Override
    public void run() {
        try {
            print();
        } catch (InterruptedException ex) {
            Logger.getLogger(Race.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void print() throws InterruptedException {
        synchronized(lock) {
            for(int i = 1; i <= 10; i++){
                System.out.println(i);
                Thread.sleep(1000);
            }
        }
    }
}

public class Interview{
    public static void main(String[] args) throws InterruptedException {
        Object lock = new Object();

        Race r1 = new Race(lock); // <== lock object
        Thread t1 = new Thread(r1, "First thread");

        Race r2 = new Race(lock); // <== same lock object
        Thread t2 = new Thread(r2, "Second thread");

        t1.start();
        t2.start();
    }
}