从run方法锁定对另一个类的访问

时间:2016-05-15 19:55:15

标签: java multithreading locking

相当复杂的代码,但这是一个非常简单的问题。

我有一个帖子,这是它的run方法:

public void run() //gets pages and writes to them
{ // i printed the pageId of every process to check they are running at the same time and competing for resources
    for(ProcessCycle currentCycle : processCycles.getProcessCycles())
    {
        Long[] longArray = new Long[currentCycle.getPages().size()];
        try {
            Page<byte[]>[] newPages = mmu.getPages(currentCycle.getPages().toArray(longArray));
            for(int i = 0; i < newPages.length; i++)
            {
                MMULogger.getInstance().write("GP:P" + id + " " + currentCycle.getPages().get(i) + " " + Arrays.toString(currentCycle.getData().get(i)), Level.INFO);
            }
            List<byte[]> currentPageData = currentCycle.getData();
            System.out.println("process id " + id);
            for(int i = 0; i < newPages.length;i++)
            {
                byte[] currentData = currentPageData.get(i);
                newPages[i].setContent(currentData);
            }
            Thread.sleep(currentCycle.getSleepMs());
        } catch (ClassNotFoundException | IOException | InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
不要费心阅读所有内容。请注意,在mmu.getpages之后有一个for循环。

当进程在for循环中时,我想锁定对所有其他线程的mmu.getpages的访问。 synchronized是不好的,因为我的原始进程不再是mmu,但是在for循环中,reentrantlock可能是一个好主意,但我不熟悉语法并遇到了一些问题。

长话短说 - 在mmu.getpages之后,如何将所有其他线程等待,而某些线程在for循环内?

2 个答案:

答案 0 :(得分:1)

通常我选择这样的方法:

private Object lock = new Object();
public void run() //gets pages and writes to them
{ // i printed the pageId of every process to check they are running at the same time and competing for resources
    for(ProcessCycle currentCycle : processCycles.getProcessCycles())
    {
        Long[] longArray = new Long[currentCycle.getPages().size()];
        try {
            synchrnonized(lock) {
                Page<byte[]>[] newPages = mmu.getPages(currentCycle.getPages().toArray(longArray));
                for(int i = 0; i < newPages.length; i++)
                {
                    MMULogger.getInstance().write("GP:P" + id + " " + currentCycle.getPages().get(i) + " " + Arrays.toString(currentCycle.getData().get(i)), Level.INFO);
                }
            }
            List<byte[]> currentPageData = currentCycle.getData();
            System.out.println("process id " + id);
            for(int i = 0; i < newPages.length;i++)
            {
                byte[] currentData = currentPageData.get(i);
                newPages[i].setContent(currentData);
            }
            Thread.sleep(currentCycle.getSleepMs());
        } catch (ClassNotFoundException | IOException | InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

不确定是否有更好的方法。这只会在所有线程共享此对象的同一实例时按预期工作,否则您必须使lock成为静态成员变量。

答案 1 :(得分:0)

在我看来,ReadWriteLock可能是最好的方法。

这样的事情:

public class MmuClass {

    private ReadWriteLock blockGetPages =  new ReentrantReadWriteLock();

    public byte [] getPages(...) {
        try{ 
           blockGetPages.readLock().lock();
           // ...
           // ...
           // ...
           return result;
        finally{ 
           blockGetPages.readLock().unlock(); 
        }
    }

    public void lockAccessToGetPages(){
        blockGetPages.writeLock().lock();
    }

    public void unlockAccessToGetPages(){
        blockGetPages.writeLock().unlock();
    }
}

Page<byte[]>[] newPages = mmu.getPages(currentCycle.getPages().toArray(longArray));
try{
     mmu.lockAccessToGetPages();
     for(int i = 0; i < newPages.length; i++) {
      MMULogger.getInstance().write("GP:P" + id + " " + currentCycle.getPages().get(i) + " " + Arrays.toString(currentCycle.getData().get(i)), Level.INFO);
   }
} finally{
    mmu.unlockAccessToGetPages();
}

在此解决方案中,所有“读者”都可以同时调用getPages(),调用lockAccessToGetPages()后访问被阻止,调用unlockAccessToGetPages()后访问被阻止。如果一个线程在写入模式下锁定对象,则只有该线程可以访问该方法。如果某个线程试图将其锁定在写入模式,则必须等到所有当前“在metod内部”的读者完成其fork并离开该方法。