2016-05-15 62 views
1

相当复杂的代码,但这是一个非常简单的问题。锁定访问另一个类,从运行方法

我有一个线程,这是它的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循环中,但我想锁定对所有其他线程的访问权限。 synchronized是不好的,因为我的原始过程不再是mmu,而是在for循环中,并且reentrantlock可能是个好主意,但我对语法不熟悉并遇到了一些问题。

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

+0

你有三个for循环,你是指哪一个?第一个for'newPages'循环? – hotzst

+0

是的。第一个,通过newPages,在mmu.getpages下面 –

+0

该代码在设计上有些破碎。这是违反直觉的,并且容易出错将某些东西锁定在getter(例如,如果在调用getPages(...)后没有解锁锁定/信号/无论什么人都不能调用getPages (......)再次)。你能否详细说明你想做什么?这似乎是[XY-Problem](http://meta.stackexchange.com/a/66378)。 – Turing85

回答

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成为静态成员变量。

+0

我复制了你的代码,它仍然允许访问mmu.getpages。线程不共享相同的实例。将其更改为私有静态对象lock = new Object();没有让事情变得更好。 –

+0

我想你误会了。而threadA是在for循环内,我想锁定所有其他线程做mmu.getpages,所以不应该它也在同步块? –

+0

然后它看起来像你的线程使用不同的类加载器。作为一个声音,你需要有一个“对象”来锁定所有线程共享的对象。变量'mmu'可能会这样做。否则,没有足够的代码来猜测。 – hotzst

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(),访问被呼叫阻止unlockAccessToGetPages()后调用lockAccessToGetPages()和畅通之后。如果一个线程以写入模式锁定对象,则只有该线程才能访问该方法。如果某个线程试图将其锁定在写入模式下,则必须等到所有当前位于metod内部的读取器完成其​​分支并离开该方法。