如何使用同步方法?

时间:2015-08-12 08:34:40

标签: java synchronization

我有这段代码。

public class Main{

    public static void main(String[] args) {
    Main1 main1 = new Main1();
    Main2 main2 = new Main2();
    Thread t1 = new Thread(main1);
    Thread t2 = new Thread(main2);
    t1.start();
    t2.start();
  }
}
public class Main1 extends Thread{
    SynchronizedCounter c = new SynchronizedCounter();
    public void run(){
        System.out.println("Entering Main1");
        c.print();
        System.out.println("Exiting Main1");
    }
}
public class Main2 extends Thread{
    SynchronizedCounter c = new SynchronizedCounter();
    public void run(){
        System.out.println("Entering Main2");
        c.print();
        System.out.println("Exiting Main2");
    }
}
public class SynchronizedCounter {
    public void print() {
        for(int  i = 1; i<10; i++){
            System.out.print(i+ " ");
        }
    }
}

当我运行此代码时,我得到不同的输出,我理解为什么。为了使它同步,我在SynchronizedCounter类中将synchronized关键字添加到print()。 现在,它看起来像这样。

public class SynchronizedCounter {
public synchronized void print() {
    for(int  i = 1; i<10; i++){
        System.out.print(i+ " ");
    }
  }
}

但是,当我运行它时,我会得到随机结果。 我不确定如何通过使方法同步来使其同步,因此,它给出了一个固定的结果。

例如:

Entering Main1
1 2 3 4 5 6 7 8 9 
Exiting Main1
Entering Main2
1 2 3 4 5 6 7 8 9 
Exiting Main2

编辑:感谢Kayaman的回答。现在工作正常。我只是在代码中稍微改变一下。它现在看起来像这样。

public class Main{

public static void main(String[] args) {
    SynchronizedCounter c = new SynchronizedCounter();
    Main1 main1 = new Main1(c);
    Main2 main2 = new Main2(c);
    Thread t1 = new Thread(main1);
    Thread t2 = new Thread(main2);
    t1.start();
    t2.start();
 }
}

public class Main1 extends Thread{
SynchronizedCounter c;
Main1(SynchronizedCounter counter){
    c = counter;
}
public void run(){
    c.print();
 }
}

public class Main2 extends Thread{
SynchronizedCounter c;
Main2(SynchronizedCounter counter){
    c = counter;
}
public void run(){
    c.print();
 }
}

public class SynchronizedCounter {
public static int i = 0;
public synchronized void print() {
    System.out.println("\n Thread "+ i);
    i++;
    for(int  i = 1; i<10; i++){
        System.out.print(i+ " ");
    }
 }
}

现在,输出结果是:

 Thread 0
1 2 3 4 5 6 7 8 9 
 Thread 1
1 2 3 4 5 6 7 8 9 

2 个答案:

答案 0 :(得分:7)

线程需要使用相同的SynchronizedCounter实例进行同步才能工作。由于代码中有2个实例,因此两个线程都可以在自己的实例上进行同步而不会阻塞。

答案 1 :(得分:0)

正如其他人已经说过的那样,synchronized方法在类的实例上进行同步,因为你有2个实际上并没有同步两个线程。

因此,根据您的需要,

  • 在两个线程中使用相同的SynchronizedCounter实例,或
  • 将synchronized块放在方法内(身体周围)并在类上同步,即synchronized(SynchronizedCounter.class) { ... }

修改

对预期输出的评论:因为您没有将线程的run()方法与那里的打印语句同步,例如System.out.println("Entering Main1");可能仍然会混淆,即使计数器正确同步,你仍然可以得到类似的东西(顺便说一下打印数字后没有换行符,我假设你会添加它):

 Entering Main2
 Entering Main1
 1 2 3 4 5 6 7 8 9 
 Exiting Main2
 1 2 3 4 5 6 7 8 9 
 Exiting Main1