假设有以下代码:
class MyClass {
synchronized void myMethod1() {
//code
}
synchronized void myMethod2() {
//code
}
}
现在假设myMethod1()
和myMethod2()
访问不同的数据;现在如果有两个线程,则线程A只调用myMethod1()
而线程B只调用myMethod2()
。
如果线程A正在执行myMethod1()
,那么线程B阻塞等待myMethod2()
,即使它们没有访问相同的数据,也没有理由这样做?据我所知,synchronized方法使用this
对象的监视器实例方法和MyClass.class
对象的静态函数监视器。
答案 0 :(得分:3)
您对情况的理解是正确的。
典型的解决方案是为相关资源分别设置专用lock objects。
class MyClass {
private final Lock lock1 = new ReentrantLock();
private final Lock lock2 = new ReentrantLock();
void myMethod1() {
lock1.lock();
try {
//code
} finally {
lock1.unlock();
}
}
void myMethod2() {
lock2.lock();
try {
//code
} finally {
lock2.unlock();
}
}
}
答案 1 :(得分:1)
你的所有假设都是正确的。在没有数据共同的情况下,没有理由在方法级别进行同步。
答案 2 :(得分:1)
sychronized
方法将锁定对象本身。因此,每个方法都必须等待另一个方法完成其释放对象的访问权限。如果您的方法真正访问不同的数据,您可以执行以下操作:
class MyClass {
private static Object mLock1 = new Object();
private static Object mLock2 = new Object();
void myMethod1() {
synchronized(mLock1) {
//code
}
}
void myMethod2() {
synchronized(mLock2) {
//code
}
}
}
然后您可以独立访问它们。
编辑:您基本上可以将同步方法视为与此等效:
void myMethod1() {
synchronized(this) {
//your code
}
}
如上所示,很清楚为什么两个同步方法相互阻塞,因为它们必须等待this
上的锁定才能释放。
答案 3 :(得分:0)
是的,将这两种方法声明为synchronized
将使它们相互阻塞,即使它们访问不同的数据元素。
为避免这种情况,您可以使用更细粒度的锁。 E.g:
class MyClass {
private static final Object lock1 = new Object();
private static final Object lock2 = new Object();
void myMethod1() {
synchronized (lock1) {
//code
}
}
void myMethod2() {
synchronized (lock2) {
//code
}
}
答案 4 :(得分:0)
您可以对myMethod1
和myMethod2
使用不同的监视器,如下所示:
class MyClass {
Object monitor1 = new Object();
Object monitor2 = new Object();
void myMethod1() {
synchornized(monitor1) {
//code
}
}
void myMethod2() {
synchronized(monitor2) {
//code
}
}
}