简体   繁体   English

同步方法无法正常工作

[英]Synchronized method is not working as expected

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();

   }
 }

This is class whose object would be accessed by two threads 该类的对象将由两个线程访问

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());
    }
  }

}

I was expecting result to be like: 我期望结果是这样的:

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

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

I know sequence could be different ie. 我知道顺序可能会不同。 'Changing name by two' could come first (1000 times) and then 'Changing name by one' (1000 times) “先改名”(1000次)然后是“先改名”(1000次)

But when I run this code I see something like this: 但是,当我运行这段代码时,我看到的是这样的:

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

In your case a thread on entering the synchronized block, executes it and leaves it in each iteration. 在您的情况下,进入synchronized块的thread将在每次迭代中执行并保留它。 Once a Thread leaves the synchronized block it leaves an opportunity for another competiting thread to aquire lock and enter the synchronized block. Thread离开synchronized块后,它将为另一个竞争thread留出机会获取lock并进入synchronized块。

For the result you expect you may modify the class MyThread 's run() method as below. 对于您期望的结果,您可以如下修改MyThread类的run()方法。

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

Also if you follow above way then you can remove the synchronized from Santhosh class setName() method. 同样,如果您按照上述方法操作,则可以从SanthoshsetName()方法中删除synchronized

PS Though you should keep proper contextual names but I understand here its just for the purpose of study but still I would suggest to rename the class MyThread to MyRunnable as its an implementation of Runnable interface and its not a Thread . PS虽然您应该保留适当的上下文名称,但是我在这里仅出于学习目的理解它,但我仍建议将MyThread类重命名为MyRunnable因为它是Runnable接口的实现,而不是Thread

Threads execute in whatever order the compiler and the processor decide. 线程以编译器和处理器决定的任何顺序执行。 This includes a mixed order, with ones between twos and twos between ones. 这包括一个混合的顺序,一个介于2和一个介于1之间。 They don't wait for other threads to finish before executing. 他们不等待其他线程完成执行。 When using threads, you should expect them running at the same time. 使用线程时,您应该期望它们同时运行。 This is how they're supposed to behave: executing at the same time (alternating if single-core processor, concurrently if multi-core processor). 它们的行为方式是:同时执行(如果是单核处理器,则交替执行;如果是多核处理器,则同时执行)。 There isn't anything wrong here. 这里没有任何问题。 synchronized is working correctly: it prevents the threads from modifying the string at the same time (that's all it's supposed to do). synchronized工作正常:它防止线程同时修改字符串(这是应该做的所有事情)。 Any execution order is correct. 任何执行顺序都是正确的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM