【问题标题】:java synchronizing access to different critical sectionsjava同步访问不同的关键部分
【发布时间】:2016-10-16 06:49:46
【问题描述】:

我有一个如下所示的方法。

public class CriticalSections
{

    public void mainMethod(boolean b)
        {
            if (b) {
                method1();
            }
            else {
                criticalMethod();
                method2();
            }
        }


        private void criticalMethod()
        {
            System.out.println("in criticalMethod");
        }

        private void method1()
        {
            System.out.println("in method1");
        }

        private void method2()
        {
            System.out.println("in method2");
        }
 }

我需要限制对这些方法的访问,以便

  1. 当线程访问criticalMethod()时,应该限制所有其他线程对method1()和method2()的访问。类似地,当线程访问method1()和method2()时,访问criticalMethod() ) 应限制用于所有其他线程。
  2. method1() 可以单独被不同的线程同时访问。
  3. method2() 可以单独被不同的线程同时访问。
  4. method1() 和 method2() 可以被不同的线程同时访问。

为了满足第一个访问条件,我想出了以下代码, 但这不会满足其他 3 个条件,因此性能会受到影响。

public class CriticalSections
{

    private final Lock lock1 = new ReentrantLock();
    private final Lock lock2 = new ReentrantLock();
    private final Lock lock3 = new ReentrantLock();

    public void mainMethod(boolean b)
    {
        if (b) {
            lock1.tryLock();
            try {
                method1();
            }
            finally {
                lock1.unlock();
            }
        }
        else {
            lock1.tryLock();
            try {
                lock2.tryLock();
                try {
                    lock3.tryLock();
                    try {
                        criticalMethod();
                    }
                    finally {
                        lock3.unlock();
                    }
                }
                finally {
                    lock2.unlock();
                }
            }
            finally {
                lock1.unlock();
            }
        }
        lock3.tryLock();
        try {
            method2();
        }
        finally {
            lock3.unlock();
        }
    }

    private void criticalMethod()
    {
        System.out.println("in criticalMethod");
    }

    private void method1()
    {
        System.out.println("in method1");
    }

    private void method2()
    {
        System.out.println("in method2");
    }
}

应该使用什么同步机制来满足上述场景?

【问题讨论】:

    标签: java multithreading locking mutex critical-section


    【解决方案1】:

    您需要的是criticalMethod 上的排他锁和method1method2 方法上的可共享锁。实现这一点的最简单方法是使用java.util.concurrent.locks.ReentrantReadWriteLock,如下所示:

    public class CriticalSections {
        private final ReadWriteLock lock = new ReentrantReadWriteLock();
    
        public void mainMethod(boolean b) {
            if (b) {
                method1();
            } else {
                criticalMethod();
                method2();
            }
        }
    
        private void criticalMethod() {
            Lock writeLock = lock.writeLock();
            writeLock.lock();
            try {
                System.out.println("in criticalMethod");
            } finally {
                writeLock.unlock();
            }
        }
    
        private void method1() {
            Lock readLock = lock.readLock();
            readLock.lock();
            try {
                System.out.println("in method1");
            } finally {
                readLock.unlock();
            }
        }
    
        private void method2() {
            Lock readLock = lock.readLock();
            readLock.lock();
            try {
                System.out.println("in method2");
            } finally {
                readLock.unlock();
            }
        }
    }
    

    如果担心性能,也可以take a look atjava.util.concurrent.locks.StampedLock(Java 8+)。

    【讨论】:

    • 感谢您的回答,一般来说,当存在涉及在某些条件下访问多个关键部分的复杂问题时,应该遵循什么方法来确保满足所有条件并确保它们正常工作(没有任何死锁等),你有什么建议吗?
    • 代码中的更正,在 try 块之前,应该是 Lock readLock = lock.readLock(); readLock.lock();
    • @themanwhosoldtheworld:感谢您的指正。我已经修复了代码 sn-p。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-19
    • 2010-09-29
    • 2021-10-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多