Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/321.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,我有两个类,我想用它们创建一个死锁。 我试图创建两个相互读取的同步函数,因此该过程将被卡住。 但是,这些函数并没有被卡住,而是继续相互调用。 我不明白为什么会发生这种情况,synchronized关键字应该在同一个函数中有另一个进程时阻止该进程进入该函数 MyRun: public class MyRun extends Thread{ MyRun1 myRun1; MyRun(){ myRun1 = new MyRun1(this); } public synchronized

我有两个类,我想用它们创建一个死锁。 我试图创建两个相互读取的同步函数,因此该过程将被卡住。 但是,这些函数并没有被卡住,而是继续相互调用。 我不明白为什么会发生这种情况,synchronized关键字应该在同一个函数中有另一个进程时阻止该进程进入该函数


MyRun:

public class MyRun extends Thread{
MyRun1 myRun1;

MyRun(){
    myRun1 = new MyRun1(this);
}

public synchronized boolean f(){
    System.out.println("MyRun.f()");
    while (!myRun1.f()){

    }

    return true;
}
}
public class MyRun1 extends Thread {
MyRun myRun;

MyRun1(MyRun myRun){
    this.myRun = myRun;
}

public synchronized boolean f(){
    System.out.println("MyRun1.f()");
    while (!myRun.f()){}

    return true;
}
}
public static void main(String[] args){
    MyRun myRun = new MyRun();
    myRun.f();
}
MyRun.f()
MyRun1.f()
MyRun.f()
MyRun1.f()
.
.
.
.
Exception in thread "main" java.lang.StackOverflowError
MyRun2:

public class MyRun extends Thread{
MyRun1 myRun1;

MyRun(){
    myRun1 = new MyRun1(this);
}

public synchronized boolean f(){
    System.out.println("MyRun.f()");
    while (!myRun1.f()){

    }

    return true;
}
}
public class MyRun1 extends Thread {
MyRun myRun;

MyRun1(MyRun myRun){
    this.myRun = myRun;
}

public synchronized boolean f(){
    System.out.println("MyRun1.f()");
    while (!myRun.f()){}

    return true;
}
}
public static void main(String[] args){
    MyRun myRun = new MyRun();
    myRun.f();
}
MyRun.f()
MyRun1.f()
MyRun.f()
MyRun1.f()
.
.
.
.
Exception in thread "main" java.lang.StackOverflowError
Main:

public class MyRun extends Thread{
MyRun1 myRun1;

MyRun(){
    myRun1 = new MyRun1(this);
}

public synchronized boolean f(){
    System.out.println("MyRun.f()");
    while (!myRun1.f()){

    }

    return true;
}
}
public class MyRun1 extends Thread {
MyRun myRun;

MyRun1(MyRun myRun){
    this.myRun = myRun;
}

public synchronized boolean f(){
    System.out.println("MyRun1.f()");
    while (!myRun.f()){}

    return true;
}
}
public static void main(String[] args){
    MyRun myRun = new MyRun();
    myRun.f();
}
MyRun.f()
MyRun1.f()
MyRun.f()
MyRun1.f()
.
.
.
.
Exception in thread "main" java.lang.StackOverflowError
输出:

public class MyRun extends Thread{
MyRun1 myRun1;

MyRun(){
    myRun1 = new MyRun1(this);
}

public synchronized boolean f(){
    System.out.println("MyRun.f()");
    while (!myRun1.f()){

    }

    return true;
}
}
public class MyRun1 extends Thread {
MyRun myRun;

MyRun1(MyRun myRun){
    this.myRun = myRun;
}

public synchronized boolean f(){
    System.out.println("MyRun1.f()");
    while (!myRun.f()){}

    return true;
}
}
public static void main(String[] args){
    MyRun myRun = new MyRun();
    myRun.f();
}
MyRun.f()
MyRun1.f()
MyRun.f()
MyRun1.f()
.
.
.
.
Exception in thread "main" java.lang.StackOverflowError

所有代码都在主线程上运行,因为您没有启动任何其他线程。因此,方法是否同步并不重要,因为执行是顺序的

您必须调用
myRun.start()
来启动
线程。如果希望新线程调用
myRun.f()
,则必须重写
run()
方法

您还必须启动另一个
线程
(类型为
MyRun1
)并重写其
run
方法


另外,与其扩展
线程
类,不如让您的类实现
可运行
接口,并将它们的实例传递给
线程
构造函数。

您的所有代码都在主线程上运行,因为您没有启动任何其他线程。因此,方法是否同步并不重要,因为执行是顺序的

您必须调用
myRun.start()
来启动
线程。如果希望新线程调用
myRun.f()
,则必须重写
run()
方法

您还必须启动另一个
线程
(类型为
MyRun1
)并重写其
run
方法


另外,与其扩展
线程
类,不如让类实现
可运行
接口,并将它们的实例传递给
线程
构造函数。

Java同步是可重入的

如果一个线程正在执行一个同步块,而该块中的代码直接或间接调用了试图在同一对象上同步的代码,那么它不会执行同步块

将其浓缩:

synchronized (myRun) {
  synchronized (myRun1) {
    synchronized (myRun) {
      System.out.println("Hello");
    }
  }
}

在这里,将打印
Hello
,因为
myRun
已在上同步的事实不会再次阻止内部块上的同步。

Java同步是可重入的

如果一个线程正在执行一个同步块,而该块中的代码直接或间接调用了试图在同一对象上同步的代码,那么它不会执行同步块

将其浓缩:

synchronized (myRun) {
  synchronized (myRun1) {
    synchronized (myRun) {
      System.out.println("Hello");
    }
  }
}

在这里,
Hello
将被打印出来,因为
myRun
已经在上面进行了同步,这一事实不会再次阻止内部块上的同步。

看起来您永远不会启动线程,所有这些代码都在同一个线程中运行。myRun.f()在主函数中,拥有一个扩展
线程的类是不够的,您必须调用
start()
才能有效地拥有一个新线程。似乎您从未启动过线程,所有这些代码都在同一个线程中运行。在主函数中,myRun.f()是不够的。拥有一个扩展
线程的类是不够的,您必须调用
start()
才能有效地创建一个新线程。但是为什么关键字synchronized没有停止函数f()的入口(第二次)?即使它是一个同步进程?@Aviad,因为只有一个线程调用该方法
synchronized
只会锁定其他线程,使其无法同时进入该方法。但是,为什么关键字synchronized不会停止(第二次)进入函数f()?即使它是一个同步进程?@Aviad,因为只有一个线程调用该方法
synchronized
只会锁定其他线程,使其无法同时进入该方法。