互斥方法 [英] Mutually exclusive methods

查看:122
本文介绍了互斥方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在学习Java多线程编程.我有以下逻辑:

I am on my way learning Java multithread programming. I have a following logic:

假设我有A类

class A {
    ConcurrentMap<K, V> map;

    public void someMethod1 () {
        // operation 1 on map
        // operation 2 on map
    }

    public void someMethod2 () {
        // operation 3 on map
        // operation 4 on map
    }
}

现在,我不需要同步"someMethod1"或"someMethod2"中的操作.这意味着,如果有两个线程同时调用"someMethod1",则无需序列化这些操作(因为ConcurrentMap可以完成此工作).

Now I don't need synchronization of the operations in "someMethod1" or "someMethod2". This means if there are two threads calling "someMethod1" at the same time, I don't need to serialize these operations (because the ConcurrentMap will do the job).

但是我希望"someMethod1"和"someMethod2"彼此互斥,这意味着当某个线程正在执行"someMethod1"时,另一个线程应等待输入"someMethod2"(但应允许另一个线程输入"someMethod1" ).

But I hope "someMethod1" and "someMethod2" are mutex of each other, which means when some thread is executing "someMethod1", another thread should wait to enter "someMethod2" (but another thread should be allowed to enter "someMethod1").

因此,简而言之,有没有一种方法可以使"someMethod1"和"someMethod2"不是互斥体,而是互斥体?

So, in short, is there a way that I can make "someMethod1" and "someMethod2" not mutex of themselves but mutex of each other?

我希望我的问题已经足够清楚了...

I hope I stated my question clear enough...

谢谢!

推荐答案

我尝试了几次使用更高级别构造的尝试,但没有想到.我认为这可能是一个使用低级API的机会:

I tried a couple attempts with higher-level constructs, but nothing quite came to mind. I think this may be an occasion to drop down to the low level APIs:

实际上,我认为您正在尝试提出一个固有的棘手问题(请参阅倒数第二个段落),并且可能不需要(请参阅最后一段).但这就是说,这是可以实现的方式,我将在此答案的结尾处留下颜色评论.

I actually think you're trying to set up a problem which is inherently tricky (see second to last paragraph) and probably not needed (see last paragraph). But that said, here's how it could be done, and I'll leave the color commentary for the end of this answer.

private int someMethod1Invocations = 0;
private int someMethod2Invocations = 0;

public void someMethod1() {
    synchronized(this) {
        // Wait for there to be no someMethod2 invocations -- but
        // don't wait on any someMethod1 invocations.
        // Once all someMethod2s are done, increment someMethod1Invocations
        // to signify that we're running, and proceed
        while (someMethod2Invocations > 0)
            wait();
        someMethod1Invocations++;
    }

    // your code here

    synchronized (this) {
        // We're done with this method, so decrement someMethod1Invocations
        // and wake up any threads that were waiting for that to hit 0.
        someMethod1Invocations--;
        notifyAll();
    }
}

public void someMethod2() {
    // comments are all ditto the above
    synchronized(this) {
        while (someMethod1Invocations > 0)
            wait();
        someMethod2Invocations++;
    }

    // your code here
    synchronized(this) {
        someMethod2Invocations--;
        notifyAll();
    }
}

上述问题的一个明显问题是,它可能导致线程饥饿.例如,someMethod1()正在运行(并阻塞someMethod2() s),并且在即将完成时,另一个线程出现并调用someMethod1().这样就可以进行了,并在完成时另一个线程开始了someMethod1(),依此类推.在这种情况下,someMethod2()将永远不会有运行的机会.实际上,这不是上面代码中的直接错误.这是您的设计需求中的一个问题,一个好的解决方案应该积极地解决这个问题.我认为 AbstractQueuedSynchronizer 可以做到这一点,尽管这是留给读者的练习. :)

One glaring problem with the above is that it can lead to thread starvation. For instance, someMethod1() is running (and blocking someMethod2()s), and just as it's about to finish, another thread comes along and invokes someMethod1(). That proceeds just fine, and just as it finishes another thread starts someMethod1(), and so on. In this scenario, someMethod2() will never get a chance to run. That's actually not directly a bug in the above code; it's a problem with your very design needs, one which a good solution should actively work to solve. I think a fair AbstractQueuedSynchronizer could do the trick, though that is an exercise left to the reader. :)

最后,我不能抗拒,只好插话一种意见:鉴于ConcurrentHashMap操作相当迅速,因此最好只在这两种方法上放一个互斥体,然后对其进行处理.因此,是的,线程将不得不排队等待调用someMethod1(),但是每个线程将非常快地完成其转弯(从而使其他线程继续进行).没问题.

Finally, I can't resist but to interject an opinion: given that ConcurrentHashMap operations are pretty darn quick, you could be better off just putting a single mutex around both methods and just being done with it. So yes, threads will have to queue up to invoke someMethod1(), but each thread will finish its turn (and thus let other threads proceed) extremely quickly. It shouldn't be a problem.

这篇关于互斥方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆