Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.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,我不熟悉同步和多线程。请回答为什么这段代码没有锁定对象b public class Tetsclass { public static void main(String[] args) { B b = new B(); A a = new A(b); A2 a2 = new A2(b); Thread t1= new Thread(a); Thread t2= new Thread(a2);

我不熟悉同步和多线程。请回答为什么这段代码没有锁定对象b

public class Tetsclass {

    public static void main(String[] args) {
        B b = new B();
        A a = new A(b);
        A2 a2 = new A2(b);
        Thread t1= new Thread(a);
        Thread t2= new Thread(a2);
        t1.start();
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        t2.start();
    }
}
class B {
    public synchronized void waitfor() {        
        synchronized (B.class) {
            System.out.println("Lock aquired  on "+System.currentTimeMillis());
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {      
                e.printStackTrace();
            }
            System.out.println("Lock released");
        }

    }
    public void readObject() {
        System.out.println("readobject by thread==="+Thread.currentThread().getName()+" on "+System.currentTimeMillis());

    }
}
class A2 implements Runnable {

    B b=null;
    public A2(B b) {
        this.b = b;
    }

    @Override
    public void run() {     
        b.readObject();     
    }
}
class A implements Runnable {

    B b=null;
    public A(B b) {
        this.b = b;
    }
    @Override
    public void run() {             
        b.waitfor();                
    }
}
我期望输出:

Lock aquired  on 1380016080337
Lock released
readobject by thread===Thread-1 on 1380016082337
但结果是:

Lock aquired  on 1380016080337
readobject by thread===Thread-1 on 1380016082337
Lock released

readObject
方法,包括从
A2#run
调用,不涉及锁获取。因此,另一个线程持有的锁对执行
readObject
的进度无关紧要

显然你对锁的语义有误解。您认为当您锁定
B.class
时,您已经锁定了“整个类”。事情的状态完全不同:
B.class
只是另一个对象,所有对象都有其关联的监视器,可以通过线程获取。互斥只发生在争用同一个锁的线程之间。作为锁的对象和它的任何方法之间都没有语义关系,这同样代表类对象vz。该类的实例


您可能产生误解的一种方式是通过
synchronized
方法上隐式使用的对象:同步实例方法获取其
this
作为锁,而同步静态方法获取其关联类对象上的锁。

,包括从
A2#run
调用它,不涉及锁获取。因此,另一个线程持有的锁对执行
readObject
的进度无关紧要

显然你对锁的语义有误解。您认为当您锁定
B.class
时,您已经锁定了“整个类”。事情的状态完全不同:
B.class
只是另一个对象,所有对象都有其关联的监视器,可以通过线程获取。互斥只发生在争用同一个锁的线程之间。作为锁的对象和它的任何方法之间都没有语义关系,这同样代表类对象vz。该类的实例

您可能产生误解的一种方式是通过
synchronized
方法上隐式使用的对象:同步实例方法获取其
this
作为锁,而同步静态方法获取其关联类对象上的锁。

因为
readObject()
不需要获取锁,它不会等待其他线程释放锁。这种混乱可能是由于您在测试类中使用了
Thread.sleep(2000)

尝试将其更改为
Thread.sleep(10000)
,然后查看输出。你会得到你想要的结果

在第一种情况下,
A2
线程将在
A
启动后等待2秒,并将不再延迟地执行,而您的
A
在获得锁时将被延迟5秒

在第二种情况下,
A2
线程将在
A
启动后等待10秒,在这些10秒内,您的
A
将启动,休眠5秒,然后释放锁,之后,您的
A2
将无延迟地执行。

由于
readObject()
不需要获取锁,因此它不会等待其他线程释放锁。这种混乱可能是由于您在测试类中使用了
Thread.sleep(2000)

尝试将其更改为
Thread.sleep(10000)
,然后查看输出。你会得到你想要的结果

在第一种情况下,
A2
线程将在
A
启动后等待2秒,并将不再延迟地执行,而您的
A
在获得锁时将被延迟5秒

在第二种情况下,
A2
线程将在
A
启动后等待10秒,在这些10秒内,您的
A
将启动,休眠5秒,然后释放锁,之后,您的
A2
将毫无延迟地执行。

其行为符合预期。 下面是在时间线上发生的事情

a
-呼叫等待(在释放锁之前休眠5秒)
a2
-调用read,打印read消息

          t          t+dt                                                 t+dt+5
 ---------|-----------|--------------------------------|--------------------------|----------
      [a starts] [print(lock acquired)]             [sleeps(5)]           [print(lock released)]
                            t+2
 ----------------------------|--------------|--------------------------|--------------
                         [a2 starts]   [print(read message)]
您的
readObject()
中没有任何类型的锁定,其行为符合预期。 下面是在时间线上发生的事情

a
-呼叫等待(在释放锁之前休眠5秒)
a2
-调用read,打印read消息

          t          t+dt                                                 t+dt+5
 ---------|-----------|--------------------------------|--------------------------|----------
      [a starts] [print(lock acquired)]             [sleeps(5)]           [print(lock released)]
                            t+2
 ----------------------------|--------------|--------------------------|--------------
                         [a2 starts]   [print(read message)]

您的
readObject()

类B对象中没有任何类型的锁定,可以同步以获得预期的输出。当前代码执行中不涉及同步。为了同步此代码并获得预期的输出,我们可以将类B修改为

class B {
    public synchronized void waitfor() {        
        synchronized (B.class) {
            System.out.println("Lock aquired  on "+System.currentTimeMillis());
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {      
                e.printStackTrace();
            }
            System.out.println("Lock released");
        }

    }
    public void readObject() {
        synchronized(B.class)
        {
        System.out.println("readobject by thread==="+Thread.currentThread().getName()+" on "+System.currentTimeMillis());
        }
    }
} 

类B对象可以同步以获得预期的输出。当前代码执行中不涉及同步。为了同步此代码并获得预期的输出,我们可以将类B修改为

class B {
    public synchronized void waitfor() {        
        synchronized (B.class) {
            System.out.println("Lock aquired  on "+System.currentTimeMillis());
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {      
                e.printStackTrace();
            }
            System.out.println("Lock released");
        }

    }
    public void readObject() {
        synchronized(B.class)
        {
        System.out.println("readobject by thread==="+Thread.currentThread().getName()+" on "+System.currentTimeMillis());
        }
    }
} 

是的,但在调用syncronized方法时,它将获取整个对象的锁。那么为什么要调用这个readObject呢?你确定你已经完整地阅读了我的答案吗?在我的第二和第三段中详细回答了您的上述问题。是的,但在调用syncronized方法时,它将获得整个对象的锁。那么为什么要调用这个readObject呢?你确定你已经完整地阅读了我的答案吗?我在第二和第三段详细回答了你的上述问题。