[英]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.