Java:如何动态同步方法

标签 java synchronization

我有以下用例:我有一个类,有两个方法 m1 和 m2。通常情况下,m1()不需要同步,但是如果有人调用m2(),那么只要m2()正在执行,m1()就需要同步。为了实现这一目标,我想出了以下代码。你能请一下吗?对此发表评论并提出更好的选择?

注意:我意识到这种情况不切实际,因为例如如果某个线程位于 m1 的中间,而其他线程调用 m2,那么就会出现问题(如果有人指出如何解决这个问题,那就太好了);尽管如此,我发现思考这个问题很有趣。

public class DynamicSync
{
    volatile MyLock lock;   
    private final MyLock DUMMY_LOCK = new DummyMyLock();
    private final MyLock SYNCHRONIZED_LOCK = new SynchronizedMyLock();

    public DynamicSync()
    {
        lock = DUMMY_LOCK;
    }

    public void dynamicallySynchronizedMethod() // this is method m1() in the question above
    {
        lock.lock();
        // some logic
        lock.unlock();
    }

    public void setLockAndExecuteLogic() // this is method m2() in the question above
    {       
        synchronized(SYNCHRONIZED_LOCK)
        {
            lock = SYNCHRONIZED_LOCK;       
            // some logic                               
        }
    }

    interface MyLock
    {
        void lock();
        void unlock();
    }

    class DummyMyLock implements MyLock
    {
        @Override
        public void lock() 
        {
        }

        @Override
        public void unlock() 
        {
        }       
    }

    class SynchronizedMyLock implements MyLock
    {
        @Override
        public synchronized void lock() 
        {
            // no op
        }

        @Override
        public void unlock() 
        {
            lock = DUMMY_LOCK;
        }       
    }
}

编辑:实际问题是:我正在设计一个对象池,我需要知道给出了多少个对象、哪些对象被发出,以及还剩下多少。所以我正在考虑维护两个集合:origSet将是一个包含所有对象的HashSet,而dynaSet将是一个ConcurrentSkipListSet,我从中给出对象并将它们放回原处。如果我需要找出origSet和dynaSet之间的区别瞬间,我需要“卡住” dyanSet 直到计算出差异。但获得这种差异将是一个非常罕见的操作,因此我的问题。

最佳答案

Java 有一个用于多线程同步的广泛 API,所以如果您不想在竞争条件的 hell 中痛苦地死去,我强烈建议您不要尝试编写类似的东西。

如果您已经读过这本书http://www.amazon.com/Java-Concurrency-Practice-Brian-Goetz ,那么你现在应该:

  • 最好的解决方案是保持不变并将线程同步问题排除在外。
  • 如果您无法保持不变,请保持防御性,并在共享内部属性时为其创建防御性副本。这称为“安全发布”
  • 如果您无法保持不变,请至少尝试使用并发集合来让您的生活更轻松。
  • 如果您确实需要开发自己的锁定系统,请看看 Java ReadWriteLock。

根据您最后的评论,我有两个建议:

  1. 如果您只需要获取集合的大小,但不使用数据对集合执行任何操作。我认为你根本不需要同步。对 getDynaSize 的调用将返回最后一个可用值:不确定何时使用它是当前值,但除非您清楚地看到处理方法中的竞争条件,否则根本不要同步。 (也许您想向我们提供更多详细信息?)

  2. 如果确实需要锁定,请使用 ReadWriteLock,

    • 它是一个可重入锁,因此,如果一个线程已经获取了该锁,则后续的尝试获取将是非阻塞的,它允许多个读取者进入,但只允许一个写入者进入。
    • 每次需要向并发集合中添加元素时,都需要获取 writer,并在添加后释放它。而且,您必须在获取大小之前获取写入锁,并在处理完成后释放它

关于Java:如何动态同步方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11556278/

相关文章:

java - Android 同步 onSensorChanged?

Java多线程同步

java - 在 Bundle 中,如何找出给定键值的类型?

java - 在空列表中查找对象类型

java - 列表与列表迭代器

java - 从照片中识别颜色 - Android

java - 列 'column' 不能为空

python - 如何在Python和C/C++中使用共享内存

java - 跨多个线程访问字符串

sql-server - 当我将 Android SQlite 与 MS SQL Server 同步时,托管同步服务器的 Tomcat 经常崩溃