同步方法无法按预期工作

时间:2017-04-22 06:15:16

标签: java multithreading

public class TestCases implements Serializable{

public TestCases() {
    // TODO Auto-generated constructor stub
}

public static void main(String[] args) {
    // TODO Auto-generated method stub
    Santhosh me = new Santhosh();
    MyThread myT1 = new MyThread(me);
    MyThread myT2 = new MyThread(me);

    Thread t1 = new Thread(myT1);
    Thread t2 = new Thread(myT2);

    t1.setName("one");
    t2.setName("two");

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

   }
 }

这是一个类,其对象将由两个线程访问

public class Santhosh {

private String name=null;

public void setName(String name){
    synchronized(this){
    System.out.println("changing name by "+Thread.currentThread().getName());
    this.name = name;
    }
  }
}

My Thread class

public class MyThread implements Runnable{

private Santhosh santhu;

public MyThread(Santhosh me){
    this.santhu = me;
}

public void run(){
    for(int i=0;i<1000;i++){
        this.santhu.setName(Thread.currentThread().getName());
    }
  }

}

我期待结果如下:

changing name by one
changing name by one
changing name by one
.
.
.
(1000 times)

changing name by two
changing name by two
.
.
.
(1000 times)

我知道序列可能有所不同,例如“将名字改为2”可以先来(1000次),然后“将名字改为1”(1000次)

但是当我运行这段代码时,我看到的是这样的东西:

changing name by one
changing name by one
changing name by two
changing name by two
changing name by two
changing name by two
changing name by two
changing name by two
changing name by two
changing name by two
changing name by two
changing name by two
changing name by two
changing name by one --- ONE here
changing name by two

2 个答案:

答案 0 :(得分:1)

在你的情况下,thread进入synchronized块,执行它并在每次迭代中离开它。一旦Thread离开synchronized广告块,就会有机会让其他竞争对手thread获取lock并输入synchronized广告块。

对于您希望的结果,您可以修改类MyThread的{​​{1}}方法,如下所示。

run()

此外,如果您按照上述方式操作,则可以从public void run(){ synchronized(me){ for(int i=0;i<1000;i++){ this.santhu.setName(Thread.currentThread().getName()); } } } synchronized方法中移除Santhosh

P.S。虽然你应该保留适当的上下文名称但我在这里理解它只是为了研究的目的,但我仍然建议将类setName()重命名为MyThread作为MyRunnable接口的实现它不是Runnable

答案 1 :(得分:0)

线程以编译器和处理器决定的顺序执行。这包括混合顺序,两者之间有两个和两个之间的顺序。在执行之前,他们不会等待其他线程完成。使用线程时,您应该期望它们同时运行。这就是它们应该如何表现的行为:同时执行(如果是单核处理器则交替,如果是多核处理器则同时执行)。这里没有任何错误。 synchronized正常工作:它可以防止线程同时修改字符串(这就是它应该做的所有事情)。任何执行顺序都是正确的。