2013-05-11 47 views
0

我有一個類boolean變量isbeingwritten。它會跟蹤文件是否正在寫入。這個類的一個函數調用一些寫入文件的線程。這些將首先檢查isbeingwritten變量的值,如果它是false,則將其設置爲true並開始寫入,否則它們將等待。在寫作結束時,他們會將值更改回false。如果這個變量是volatile變量應該變得易變嗎?

class A 
{ 
    public boolean isbeingwrittenfalse; 
    public void func() 
    { 
     new thread1(); 
     new thread2(); 
    } 
    class thread1 implements Runnable 
    { 
     Thread t; 
     thread1() 
     { 
      t=new Thread (this); 
      t.start(); 
     } 
     public void run() 
     { 
      while(isbeingwritten); 
      isbeingwritten=true; 
      //wrrite very long string 
      isbeingwritten=false; 
     } 
    } 
    class thread2 implements Runnable 
    { 
     Thread t; 
     thread2() 
     { 
      t=new Thread (this); 
      t.start(); 
     } 
     public void run() 
     { 
      while(isbeingwritten); 
      isbeingwritten=true; 
      //wrrite very long string 
      isbeingwritten=false; 
     } 
    } 

下才是正確的解決

public class XSSThread implements Runnable { 
    Thread xt; 

    public void init() { 
     xt = new Thread(this); 
     xt.start(); 
    } 

    public void run() { 
     new Thread1().init(); 
     new Thread2().init(); 
    } 

    public synchronized void saveToFile(String a) { 
     File aFile = new File("filename.txt"); 
     try { 
      BufferedWriter out = new BufferedWriter(new FileWriter(aFile, aFile.exists())); 
      out.write(a + "\r\n"); 
      out.close(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

public class Thread1 extends XSSThread implements Runnable{ 
    Thread xt1; 

    public void init() { 
     xt1 = new Thread(this); 
     xt1.start(); 
    } 

    public void run() { 
     String a;//very long string 
     saveToFile(a); 
    } 
} 

public class Thread2 extends XSSThread implements Runnable { 
    Thread xt2; 

    public void init() { 
     xt2 = new Thread(this); 
     xt2.start(); 
    } 

    public void run() { 
     String a;//very long string 
     saveToFile(a); 
    } 
} 
+0

現在同步正確。但是,您不應該完全改變問題,因爲這會讓其他人難以將其與答案匹配。請再次更改,以便它包含原始問題和修訂問題。 – nosid 2013-05-11 10:09:39

回答

5

不,這是不正確的,因爲這兩個線程可以看到isbeingwritten == false之前都更新領域truevolatileAtomicBoolean都不能解決此問題。您應該使用適當的同步機制:

private Object writeLock = new Object(); 
class thread1 implements Runnable{ 
    public void run(){ 
     synchronized (writeLock) { 
      //write very long text 
     } 
    } 
} 
class thread2 implements Runnable{ 
    public void run(){ 
     synchronized (writeLock) { 
      //write very long text 
     } 
    } 
} 
+0

當(isbeingwritten)while(isBeingRead == true){try {wait(); \t} catch(InterruptedException e){}} – user2318314 2013-05-11 09:56:15

+0

@ user2318314:'wait'等待另一個線程調用'notify',但在您的示例中沒有'notify'。你的意思是不同的? – nosid 2013-05-11 10:00:09

+0

讓我編輯並把我正在嘗試的確切代碼.. – user2318314 2013-05-11 10:02:50

0

是,如果你想使你的isbeingwritten在同一時間,那麼你必須使用volatile關鍵字由一個線程訪問。

volatile修飾符告訴JVM訪問變量的線程必須始終將自己的變量專用副本與 內存中的主副本進行協調。

易變變量共享​​關鍵字oj java的可見性功能。這意味着線程會自動查看volatile變量的最新值。

您可以使用它像the.se

public class FileReadingWritingTask extends Thread { 

    private volatile boolean isbeingwritten; 

    public void run() { 
     if (!isbeingwritten) { 
      isbeingwritten = true; 
      // do some stuff... 

      // stuff ends 
      tellMeToStop(); 

     } 
    } 

    public void tellMeToStop() { 
     isbeingwritten = false; 
    } 
}