【问题标题】:Java method synchronization improper usage?Java方法同步使用不当?
【发布时间】:2013-11-01 23:13:27
【问题描述】:

假设有以下代码:

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

    synchronized void myMethod2() {
        //code
    }
}

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

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

【问题讨论】:

    标签: java multithreading synchronization


    【解决方案1】:

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

    典型的解决方案是为相关资源设置单独的专用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();
          }    
        }
    }
    

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案3】:

        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 上的锁释放。

        【讨论】:

        • @DuncanJones 哦,我想我们在大约 10 秒内互相发帖。编辑:也不确定你所说的“可疑”是什么意思
        • @DuncanJones 啊,np。 :)
        【解决方案4】:

        是的,将这两种方法都声明为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 
                }
        }
        

        【讨论】:

        【解决方案5】:

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-03-30
          • 1970-01-01
          • 2014-07-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多