2016-05-15 64 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內部的讀取器完成其​​分支並離開該方法。