3

假设有以下代码:

class MyClass {
    synchronized void myMethod1() {
        //code 
    }

    synchronized void myMethod2() {
        //code
    }
}

现在假设myMethod1()myMethod2()访问不同的数据;现在如果有两个线程,线程 A 只调用myMethod1(),线程 B 只调用myMethod2()

如果线程 A 正在执行,即使线程 B 不访问相同的数据并且没有理由这样做myMethod1(),线程 B 也会阻塞等待吗?myMethod2()据我所知,同步方法this对实例方法使用对象的监视器,MyClass.class对静态函数使用对象的监视器。

4

5 回答 5

3

你对情况的理解是正确的。

典型的解决方案是为相关资源设置单独的专用锁对象

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();
      }    
    }
}
于 2013-11-01T14:59:45.120 回答
1

你的所有假设都是正确的。在没有共同数据的情况下,没有理由在方法级别进行同步。

于 2013-11-01T15:00:04.270 回答
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释放。

于 2013-11-01T15:01:48.363 回答
0

是的,将这两种方法声明为synchronized会使它们相互阻塞,即使它们访问不同的数据元素也是如此。

为避免这种情况,您可以使用更细粒度的锁。例如:

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 
        }
}
于 2013-11-01T15:01:25.977 回答
0

您可以使用不同的监视器,myMethod1如下myMethod2所示:

class MyClass {
    Object monitor1 = new Object();
    Object monitor2 = new Object();
    void myMethod1() {
        synchornized(monitor1) {
        //code 
        }
    }

    void myMethod2() {
        synchronized(monitor2) {
        //code
        }
    }
}
于 2013-11-01T15:02:34.343 回答