Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/359.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 - Fatal编程技术网

Java 为什么这个线程允许另一个线程访问它的同步方法?

Java 为什么这个线程允许另一个线程访问它的同步方法?,java,Java,我有以下代码。我期望一个线程完全执行其同步方法,然后允许另一个线程访问同一方法。然而,情况并非如此 public class Threads { /** * @param args */ public static void main(String[] args) { //Thread Th = new Threads(); Thread th = new Thread (new thread1 ()); t

我有以下代码。我期望一个线程完全执行其同步方法,然后允许另一个线程访问同一方法。然而,情况并非如此

public class Threads  {

    /**
     * @param args
     */
    public static void main(String[] args) {
        //Thread Th = new Threads();
        Thread th = new Thread (new thread1 ());
        th.start();
        Thread th1 = new Thread (new thread1 ());
        th1.start();
    }
}



class thread1 implements Runnable{
    String name = "vimal";

    public void run() {
        System.out.println("Runnable "+this.name);
        setNAme("Manish");

    }

    public synchronized void setNAme(String name){
        try {
            System.out.println("Thread "+Thread.currentThread().getName());
            wait(1000);
            this.name = name;
            System.out.println("Name "+this.name);

        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }   
    }   
}
我有一个输出作为

Runnable vimal
Thread Thread-0
Runnable vimal
Thread Thread-1
Name Manish
Name Manish

这里的synchronized有什么用?我如何使我的方法在其他人访问它之前完全运行?

您必须删除对等待(1000)的调用。看起来您真正想要的是调用线程。sleep(1000),如果您只是想暂停当前线程,这不会释放任何监视器的所有权

从对象的javadoc.wait()

此方法导致当前线程(称为T)将自身置于 为该对象设置的等待,然后放弃任何和所有 此对象上的同步声明。线程T将被禁用 线程调度的目的和休眠,直到四件事之一 发生:

  • 另一个线程调用这个对象的notify方法,而线程T恰好被任意选择为要调用的线程 觉醒了
  • 其他一些线程为此对象调用notifyAll方法
  • 另一个线程中断了线程T
  • 指定的实时时间已过,或多或少。但是,如果超时为零,则不考虑实时性 线程只需等待通知
然后从该对象的等待集中删除线程T,并 重新启用线程调度。然后它以通常的方式竞争 与其他线程在对象上进行同步的权限;一旦 已获得对对象的控制,其所有同步声明 对象恢复到原来的状态,即 在调用wait方法时的情况。螺纹T 然后从wait方法的调用返回。因此,作为回报 在wait方法中,对象的同步状态和 线程T与调用wait方法时完全相同


更新:如其他答案所述,您没有在同一对象上同步。一旦你这样做了,由于我提到的问题,你仍然会遭受相同的输出。您需要修复这两个问题以获得所需的结果。

您必须取消对等待(1000)的调用。看起来您真正想要的是调用线程。sleep(1000),如果您只是想暂停当前线程,这不会释放任何监视器的所有权

从对象的javadoc.wait()

此方法导致当前线程(称为T)将自身置于 为该对象设置的等待,然后放弃任何和所有 此对象上的同步声明。线程T将被禁用 线程调度的目的和休眠,直到四件事之一 发生:

  • 另一个线程调用这个对象的notify方法,而线程T恰好被任意选择为要调用的线程 觉醒了
  • 其他一些线程为此对象调用notifyAll方法
  • 另一个线程中断了线程T
  • 指定的实时时间已过,或多或少。但是,如果超时为零,则不考虑实时性 线程只需等待通知
然后从该对象的等待集中删除线程T,并 重新启用线程调度。然后它以通常的方式竞争 与其他线程在对象上进行同步的权限;一旦 已获得对对象的控制,其所有同步声明 对象恢复到原来的状态,即 在调用wait方法时的情况。螺纹T 然后从wait方法的调用返回。因此,作为回报 在wait方法中,对象的同步状态和 线程T与调用wait方法时完全相同


更新:如其他答案所述,您没有在同一对象上同步。一旦你这样做了,由于我提到的问题,你仍然会遭受相同的输出。您将需要修复这两个问题以获得所需的结果。

synchronized
在这里不起作用,因为在这两种情况下,您没有在同一对象上同步。当应用于实例方法时,
synchronized
关键字会使该方法在
上同步。因此,在每种情况下,您都在
thread1
的实例上进行同步,其中有两个实例

更有趣的测试是在两个线程中同时运行相同的
thread1
实例。在这种情况下,调用
wait(1000)
是一件非常糟糕的事情,因为(如文档所述)它会释放
上的锁。您希望在代码中使用
Thread.sleep(1000)

如果需要两个
thread1
实例,则需要在某个共享对象上进行同步,可能如下所示:

private static final Object lockObject = new Object();

public void setName(String newName) {
    synchronized(lockObject) {
        doSetName(newName);
    }
}

synchronized
在这里不起作用,因为在这两种情况下,您没有在同一对象上同步。当应用于实例方法时,
synchronized
关键字会使该方法在
上同步。因此,在每种情况下,您都在
thread1
的实例上进行同步,其中有两个实例

更有趣的测试是在两个线程中同时运行相同的
thread1
实例。在这种情况下,调用
wait(1000)
是一件非常糟糕的事情,因为(如文档所述)它会释放
上的锁。您希望在代码中使用
Thread.sleep(1000)

如果需要两个
thread1    public static void main(String[] args) {
        Data data = new Data();

        Thread task1 = new Thread(new UpdateTask(data));
        task1.start();
        Thread task2 = new Thread(new UpdateTask(data));
        task2.start();
    }
}
class UpdateTask implements Runnable {
    private Data data;

    public UpdateTask(Data data) {
        this.data = data;
    }

    public void run() {
        try {
            data.updateData();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

    class Data {
    public synchronized void updateData() throws InterruptedException {
        for (int i = 0; i < 5; i++) {
            Thread.sleep(5000);
            System.out.println(i);
        }
    }

}