2015-05-25 2 views
0

Следующий код был обобщен приложение, приложение случайно заперли вДве нити, обращающиеся же применение переменной блокировки

время (флаг)

Этот код, работающий на моей машине попадается , в другой машине он закончил нормально

выход генерируется здесь:

INIT 
END 
before while 
before flag 
after flag 

Код:

package threads; 

public class Run implements Runnable { 

private Thread thread; 
private boolean flag = true; 

public void init() { 
    thread = new Thread(this); 
    thread.setName("MyThread"); 
    thread.start(); 
} 

@Override 
public void run() { 
    try { 

     int i = 0; 
     while (i < 1000) { 
      i++; 
     } 
     System.out.println("before flag"); 
     flag = false; 
     System.out.println("after flag"); 

    } catch (Exception e) { 
     e.printStackTrace(); 
    } finally { 
     flag = false; 
    } 
} 

public void end() { 
    thread.interrupt(); 
    thread = null; 

    System.out.println("before while"); 
    while (flag) { 
     // try { Thread.sleep(100);} catch (InterruptedException e) {} 
    } 
    ; 
    System.out.println("after while"); 
} 

public static void main(String[] args) { 
    Run r = new Run(); 
    System.out.println("INIT"); 
    r.init(); 
    System.out.println("END"); 
    r.end(); 
} 
} 

Почему, когда я изменить значение флага основной поток не проходит через петлю?

+0

Что бы вы хотели, чтобы ваш код выполнял/демонстрировал? Поскольку вы создаете новый поток в 'main' (вызывая' Run.init() '), не гарантируется, что' Run.run() 'заканчивается перед вызовом' Run.end() '. –

+0

в этом примере он должен заканчиваться нормально, но здесь он блокируется во время (флаг). В приложении, run() записывает аудио и end() останавливает запись. – patricK

ответ

1

Изменить

private boolean flag = true; 

в

private volatile boolean flag = true; 

Без volatile, нет никакой гарантии, ожидающий поток должен видеть значение обновляется. HotSpot может даже встроить while(flag) в while(true), если петля достаточно спина.

См. Memory Consistency Errors.


Кроме того, то, что вы делаете, называется spinlock. Обычно вы должны использовать thread.join(). Спин-блокировка расточительна для ресурсов, потому что ожидающий поток фактически работает (проверяя переменную) все время, которое он должен ожидать.

+0

Я попытаюсь использовать volatile. Почему, если у меня есть цикл Thread.sleep() внутри, он работает? – patricK

+0

Независимо от того, зависит ли HotSpot от условия цикла, сколько циклов цикла выполняется. Если вы «спите», он будет проходить только один или два раза. Это просто гипотеза, но я видел похожие примеры, где HotSpot делает это. В любом случае вы абсолютно должны использовать 'volatile' или другую синхронизацию для переменной, которая разделяется между потоками. – Radiodef

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