繁体   English   中英

为什么在获取对象锁定时调用非同步方法?

[英]Why does the non synchronized method get called while acquiring the lock on object?

我是同步和多线程的新手,请回答为什么此代码未锁定对象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的执行进度readObject

显然您对锁的语义有误解。 您认为锁定B.class ,就锁定了“整个类”。 事物的状态完全不同: B.class只是另一个对象,所有对象都有其关联的监视器,该监视器可以由线程获取。 互斥仅发生在争夺一个锁的线程之间。 作为锁的对象与其任何方法之间没有语义关系,并且类对象vz代表相同的关系。 该类的实例。

你的误解可能会出现的一个方法是通过对隐含使用的对象synchronized方法:一,同步实例方法获得它this作为一个锁,而同步的静态方法获得与其关联的类对象的锁。

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

a -呼叫等待(其释放锁之前睡5秒) a2 -通话读取它打印读消息。

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

readObject()没有任何类型的锁定

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

尝试将其更改为Thread.sleep(10000)并查看输出。 您会得到理想的结果。

在第一种情况下, A2线程将在A启动后等待2秒钟 ,并且将在没有任何进一步延迟的情况下执行,而您的A在获得锁后将被保持5秒钟

在第二种情况下, A启动后A2线程将等待10秒 ,在这10秒内 ,您的A将启动,睡眠5秒钟并释放锁,此后您的A2将被无延迟执行。

可以同步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());
        }
    }
} 

暂无
暂无

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

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