2013-08-28 3 views
4

Как получить доступ к статической переменной из многих потоков одновременно.Статическая переменная многопоточного доступа Java

Если у меня есть класс, как

Class A { 
    public static boolean FLG=false; 
    ..................... 
    .................... 
} 

И мне нужно, чтобы получить доступ к значению из потока 1, как

.................... 
public void run() { 
    boolean t1=A.FLG; 
    .................. 
} 

и от нити 2 Мне нужно установить значение как

.................... 
public void run() { 
    A.FLG=true; 
    .................. 
} 

Означает ли это нарушение памяти?. Если да, то какой рекомендуемый метод справиться с такой ситуацией ?.

ответ

3

Wrap статическая переменная в синхронном методе и вызвать метод, как вам нравится

public static synchronized void method1(){ 
//Whatever 
} 

public static synchronized void method2(){ 
//Whatever again 
} 

Следует отметить, что существуют и другие способы синхронизации доступа к методу. Они считаются более эффективными в средах, где заняты потоки, обращаясь к тем же методам.

Проверьте класс ReentrantLock. Есть также ответы для when to use synchronized and RentrantLock и еще много информации, которая может быть найдена через google.

Также как ответ peter и комментарий muel. Маркировка переменной boolean как изменчивой должна быть полезна. volatile Булево значение будет NOT кэш это начальное значение (false или true). JVM может делать это иногда, что может быть неожиданным для программиста.

+1

Почему бы просто не использовать летучий? – Muel

+0

@Muel, под редакцией. Спасибо :) –

+0

Если переменная используется точно так, как это видно в примере кода. Поле может быть полностью незащищенным. Thread 2 установит его значение, и Thread 1 в конце концов увидит это изменение. Если чтение устаревших значений допустимо, 'volatile' может быть опущен, так как записи в booleans являются атомарными на 32-битных платформах. –

3

Если все, что вы хотите сделать, это установить и установить примитив, вы можете сделать его volatile, и он будет потокобезопасным для этих операций.

+0

Мне нужно получить доступ к значению, а также установить значение – Haris

+0

Хм, интересно. Я думаю, что это правда [«ключевое слово« volatile »в Java плохо документировано, плохо понимается и редко используется») (http://www.javamex.com/tutorials/synchronization_volatile.shtml). Во всяком случае, [выглядит как] (http://stackoverflow.com/a/7943472/56285) 'volatile' не совсем эквивалентно тому, чтобы аксессоры попадали в поле' synchronized'. – Jonik

1

В классе А, вы можете создать набор и получить метод FLG как:

public static synchronized boolean getFlag() 
{ 
return FLG; 
} 

public static synchronized setFlag(boolean flag) 
{ 
FLG=flag; 
} 

Теперь из других потоков, значения доступа FLG usng этого метода. Это будет поддерживать значение FLG Согласовано на нескольких потоках.

+0

Как насчет установки FLG я могу следовать тем же – Haris

+0

Я отредактировал свой ответ, вы можете установить значение, подобное этому. – Nargis

1

Вы можете получить некоторую нежелательную ситуацию, когда два потока пытаются установить разные значения в статическую переменную, и вы не уверены, что именно на самом деле это действительно значение. Лучший способ (подумав в простом сценарии), я думаю, что он использует AtomicBoolean (http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicBoolean.html), и вы получаете значение в объекте и используете его (вместо использования объекта все время, из-за того, что другой поток может его изменить, и вы можете получить неожиданный сценарий).

Еще одно предложение - использовать Byteman для создания параллельных тестов.

С уважением, Луан

0

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

Пример:

public class A extends Thread{ 

    public static boolean FLG=false; 

    public A(String threadName) { 
     start(); 
     setName(threadName); 
    } 

    @Override 
    public void run() { 
     // TODO Auto-generated method stub 
     while(true){ 
      if(this.getName().equals("getterThread") && FLG == true){ 
       boolean t1=A.FLG; 
      } 
      if(this.getName().equals("setterThread") && FLG == false){ 
       A.FLG = true; 
      } 
     } 

    } 

    public static void main(String[] args) { 

     A dad = new A("getterThread"); 
     A son = new A("setterThread"); 
    } 
}