Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/352.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 同步方法未按预期工作_Java_Multithreading - Fatal编程技术网

Java 同步方法未按预期工作

Java 同步方法未按预期工作,java,multithreading,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();

这个类的对象将由两个线程访问

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;
    }
  }
}
我知道顺序可能会有所不同,即“更改两个名称”可能先出现(1000次),然后“更改一个名称”(1000次)

但当我运行这段代码时,我看到如下内容:

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

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

线程以编译器和处理器决定的任何顺序执行。这包括一个混合顺序,一个在两个之间,两个在一个之间。在执行之前,它们不会等待其他线程完成。当使用线程时,您应该期望它们同时运行。这就是它们的行为方式:同时执行(如果是单核处理器,则交替执行,如果是多核处理器,则并发执行)。这里没有什么问题
synchronized
工作正常:它防止线程同时修改字符串(这就是它应该做的全部工作)。任何执行顺序都是正确的。

在您的例子中,一个
线程
在进入
synchronized
块时,执行它并在每次迭代中保留它。一旦一个
线程
离开
同步
块,它就为另一个竞争
线程
留下机会,以获得
锁定
并进入
同步

对于预期的结果,您可以修改类
MyThread
run()
方法,如下所示

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
public void run(){
同步(me){

对于(int i=0;我认为这是对同步的一点误解。如果我的记忆对我来说是对的,你永远不应该对并发线程执行的顺序做出假设——这完全取决于编译器和处理器。你为什么要创建线程来产生这种输出?只是为了测试一些东西?不过,
synchronized
b锁按预期工作。任何执行命令都是正确的。这里没有问题。除了您的预期中存在明显的误解外,该示例非常人为。它可能会帮助您考虑一个现实情况;您应该特别考虑如何处理您编写的值。(事实上,即使这里没有同步,字段写入也是原子性的,但这也无关紧要,因为没有人观察到原子性的缺失。)另外,值得指出的是,synchronized不仅需要用于互斥,还需要用于可见性:一个线程的写操作在没有synchronized的情况下不一定对另一个线程可见,即使没有竞争条件。
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
public void run(){
    synchronized(me){
          for(int i=0;i<1000;i++){
            this.santhu.setName(Thread.currentThread().getName());
          }
    }
  }