2016-07-15 4 views
2

У меня есть простая Java-программа с 3 потоками, каждая из которых увеличивается, а затем печатает переменную counter. Код Java это- Неожиданный результат Java Multi-Threading

public class test implements Runnable { 

    private int counter=0; 

    public static void main(String args[]){ 

     test t=new test(); 
     Thread t1=new Thread(t,"THREAD 1"); 
     Thread t2=new Thread(t,"THREAD 2"); 
     Thread t3=new Thread(t,"THREAD 3"); 
     t1.start(); 
     t2.start(); 
     t3.start(); 

    } 

    public void run(){ 

     counter=counter+1; 
      System.out.println(Thread.currentThread().getName()+" "+ counter); 

    } 
} 


Понимание того, что метод run не синхронизирован нити могут перемежать любым способом дает никакого результата, но результат я получаю в основном (я запустить программу несколько раз)

это-
THREAD 1 2 
THREAD 3 3 
THREAD 2 2 


Я не понимаю, почему 1 никогда не печатается и даже после печати 3, 2 снова печатается (с момента последнего значения counter было установлено до 3, как печатается).

Кроме того, является переменная counter разделяемая среди 3-х потоков? Он будет передан, если я сделаю это static, но что в этом случае.
Пожалуйста, объясните.

+1

Вы передаете один и тот же экземпляр 't' в свои 3 потока, поэтому все они используют один и тот же экземпляр' counter'. Кроме того, поле 'counter' модифицируется несколькими потоками и не имеет синхронизации, поэтому ваши вычисления, вероятно, являются только cpu-памятью и не сохраняются в реальной памяти, что может привести к фанк-результатам –

+0

@RobinJonsson, поэтому в общем случае переменные класса будут если я передаю один и тот же экземпляр объекта при создании потоков, или если я использую static, иначе они получат отдельный стек стека? –

ответ

1

Если вы используете

test tOne=new test(); 
    test tTwo=new test(); 
    test tThree=new test(); 
    Thread t1=new Thread(tOne,"THREAD 1"); 
    Thread t2=new Thread(tTwo,"THREAD 2"); 
    Thread t3=new Thread(tThree,"THREAD 3"); 
    t1.start(); 
    t2.start(); 
    t3.start(); 

выход будет что-то вроде

THREAD 2 1 
THREAD 1 1 
THREAD 3 1 

counter разделили, потому что вы использовали один и тот же экземпляр т во всех трех потоков.

+0

О, я понял это сейчас. Благодарю. А как насчет печатного материала. Значение 1 никогда не печатается, и как получилось, что 2 пришел снова после того, как счетчик был установлен в 3. –

+0

@ Brut3Forc3 Какое значение видно по потокам, непредсказуемо, потому что синхронизации нет. В этом весь смысл, почему вам нужна синхронизация. – Fildor

+0

@Fildor Я просто попытался использовать статическое ключевое слово для переменной счетчика, но результат все равно кажется почти таким же. –

2

Прежде всего, переменная экземпляра разделяется всеми потоками, потому что они используют один и тот же экземпляр класса runnable (в вашем коде есть только один раз «новый тест()»).

Почему значение 1 никогда не печатается? Это немного сложнее ответить, потому что порядок инструкций определяется реализацией JVM, операционной системой и аппаратным обеспечением (в целом это непредсказуемо). В вашем случае кажется, что функция печати вызывается после двух инструкций приращения. (если вы считаете, что печать медленнее, чем приращение переменной, это имеет смысл).

Наконец, значение 2 может быть напечатано после значения 3, так как функция println не синхронизирована, это означает, что также команда внутри функции печати может чередоваться. Поэтому в этом случае функция печати во втором потоке вызывается перед функцией на третьем потоке, но первая, которая завершена, является третьим потоком.

Я надеюсь, что это может вам помочь.

+0

Да, да. Большое спасибо: D. –

Смежные вопросы