互斥量优先于JAVA

时间:2016-02-09 15:23:44

标签: java multithreading mutex semaphore

我需要优先构建我称之为“Unfair Semaphore”的东西。 例如:当具有priority = 1的线程想要获取信号量时,它只需要等到具有相同优先级的另一个线程完成,然后它就可以acquire()。但是当priority = 2的线程想要获取信号量时,它必须等待所有priority = 1的线程在使用信号量之前完成,然后尝试acquire()。 我总共有4个不同的优先事项。 这是我尝试的但是没有用。

有人有解决方案吗?

public class UnfairSemaphore
{
    private Semaphore mPrior1;
    private Semaphore mPrior2;
    private Semaphore mPrior3;
    private Semaphore mPrior4;

    public UnfairSemaphore()
    {
        mPrior1 = new Semaphore(1);
        mPrior2 = new Semaphore(1);
        mPrior3 = new Semaphore(1);
        mPrior4 = new Semaphore(1);
    }

    public void acquire(int priority) throws InterruptedException
    {
        if(priority == 1)
        {
            mPrior1.acquire();
        }
        else if(priority == 2)
        {
            while(mPrior1.hasQueuedThreads() && mPrior1.availablePermits() <=0)
            {
                //wait();
            }
            mPrior2.acquire();
            mPrior1.acquire();
        }
        else if(priority == 3)
        {
            while(mPrior1.hasQueuedThreads() && mPrior1.availablePermits() <=0 && mPrior2.hasQueuedThreads() && mPrior2.availablePermits() <=0)
            {
                //wait();
            }
            mPrior3.acquire();
            mPrior2.acquire();
            mPrior1.acquire();
        }
        else
        {
            while(mPrior1.hasQueuedThreads() && mPrior1.availablePermits() <=0 && mPrior2.hasQueuedThreads() && mPrior2.availablePermits() <=0 && mPrior3.hasQueuedThreads() && mPrior3.availablePermits() <=0)
            {
                //wait();
            }
            mPrior4.acquire();
            mPrior3.acquire();
            mPrior2.acquire();
            mPrior1.acquire();
        }
    }

    public void release(int priority)
    {
        if(priority == 1)
        {
            mPrior1.release();
        }
        else if(priority == 2)
        {           
            mPrior1.release();
            mPrior2.release();          
        }
        else if(priority == 3)
        {           
            mPrior1.release();
            mPrior2.release();
            mPrior3.release();
        }
        else
        {           
            mPrior1.release();
            mPrior2.release();
            mPrior3.release();
            mPrior4.release();
        }
        //notifyAll();
    }
}

2 个答案:

答案 0 :(得分:0)

基本要求是,我们有一堆等待线程,每个线程都有一个优先级。在release()上,我们选择具有最高优先级的等待线程,并将其唤醒。

这可以通过LockSupport中的主题park()unpark()来完成。它是一种低级并发工具,但我们不会将它用于精英;我们使用它是因为它最自然地模拟我们的解决方案。

首先,我们需要一个存储等待线程及其优先级的数据结构。你可以通过很多方式做到这一点。

    void storeWaitingThread(Integer priority, Thread thread) { ... }

    // select and remove a waiting thread with highest priority; return null if none.
    Thread selectWaitingThread(){ ... }

现在,release()只会选择一个等待的帖子并unpark

final Object lock = new Object();

volatile Thread owningThread;

public void release()
{
    synchronized (lock)
    {
        Thread nextOwner = selectWaitingThread();
        owningThread = nextOwner;
    }
    LockSupport.unpark(owningThread);
}

acquire(priority)将当前线程存储为等待线程;停车直到被选中

public void acquire(int priority)
{
    Thread thisThread = Thread.currentThread();
    synchronized (lock)
    {
        if(owningThread==null)
        {
            owningThread=thisThread;
            return;
        }
        storeWaitingThread(priority, thisThread);
    }

    while(owningThread!=thisThread)
    {
        LockSupport.park();
        // interrupt ignored. // todo handle interrupt
    }
}

请参阅https://gist.github.com/zhong-j-yu/3ea91194f55d91059789

的完整代码

请注意,我们的acquire会忽略中断。如果它应该在中断时保释,请在park()唤醒后添加一些逻辑。

答案 1 :(得分:-1)

为什么要自己管理线程?

您应该使用Thread类中的synchronised关键字和setPriority方法。

请查看以下链接:

https://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#setPriority%28int%29

https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html