2013-05-11 2 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

ответ

5

Нет, это не правильно, потому что оба потока могут видеть isbeingwritten == false перед тем как обновить поле для true. Ни volatile, ни AtomicBoolean решить эту проблему. Вы должны использовать надлежащие механизмы синхронизации:

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

+0

@ user2318314: 'wait' ждет, пока другие потоки не назовут' notify', но в вашем примере нет 'уведомления '. Вы имеете в виду что-то другое? – nosid

+0

Позвольте мне изменить и поместить точный код, который я пытаюсь. – user2318314

0

Да, если вы хотите, чтобы ваш isbeingwritten доступ один поток в то время, то вы должны использовать энергонезависимую ключевое слово.

Модификатор volatile сообщает JVM, что поток, обращающийся к переменной, должен всегда согласовывать свою собственную частную копию переменной с основной копией в памяти .

Неустойчивые переменные совместно используют функции видимости synchronized Ключевые слова oj java. Это означает, что потоки автоматически видят самое последнее значение для переменных переменных.

Вы можете использовать его как 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; 
    } 
} 
Смежные вопросы