2015-04-28 3 views
2

У меня есть сотовый класс, представляющий одно значение и в ячейке класс swapThread которого запустить метод просто вызвать метод swapValue().Синхронизированные темы поведение

public static void main(String[] args) throws InterruptedException { 

    Cell c1 = new Cell(15); 
    Cell c2 = new Cell(23); 

    Thread t1 = new swapThread(c1, c2); 
    Thread t2 = new swapThread(c2, c1); 

    t1.start(); 
    t2.start(); 
} 

класс Сотовый:

class Cell { 
private static int counter = 0; 
private int value, id; 

public Cell(int v) { 
    value = v; 
    id = counter++; 
} 

synchronized int getValue() { 
    return value; 
} 

synchronized void setValue(int v) { 
    value = v; 
} 

void swapValue(Cell other) { 

    int t = getValue(); 
    System.out.println("Swapping " + t); 
    int v = other.getValue(); 
    System.out.println("with " + v); 
    setValue(v); 
    other.setValue(t); 

    System.out.println("Cell is now " + getValue()); 
    System.out.println("Cell was " + other.getValue()); 
} 

} 

и класс swapThread:

class swapThread extends Thread { 
Cell cell, othercell; 

public swapThread(Cell c, Cell oc) { 
    cell = c; 
    othercell = oc; 
} 

public void run() { 

    cell.swapValue(othercell); 

} 
} 

Обычный выход:

Swapping 15 
Swapping 23 
with 23 
with 15 
Cell is now 23 
Cell is now 15 
Cell was 15 
Cell was 23 

Я могу просто дождаться, когда thread1 завершится с Thread.join() в основном методе, но есть ли способ избежать этого, изменив синхронизированные методы.

+0

в 'swapValue()', перед сменой, вам нужно сначала получить блокировку на обеих ячейках ('' this' и other') для выполнения операции атомарно. –

+0

Обмен не является атомарным в соответствии с вашей реализацией. –

+0

Есть ли способ решить проблему, не вставляя какие-либо блокирующие объекты? – Nikola

ответ

1

Вы можете достичь последовательного выполнения swapValues() путем этот статический метод и синхронизируются:

static synchronized void swapValues(Cell c1, Cell c2) { 

    int t = c1.getValue(); 
    System.out.println("Swapping " + t); 
    int v = c2.getValue(); 
    System.out.println("with " + v); 
    c1.setValue(v); 
    c2.setValue(t); 

    System.out.println("Cell is now " + c1.getValue()); 
    System.out.println("Cell was " + c2.getValue()); 
} 

Таким образом, вы синхронизировать его на Cell.class, что делает swapValues() должны выполняться последовательно.

Обратите внимание, теперь вы должны пройти 2 клетки в нем:

public void run() { 
    Cell.swapValues(cell, othercell); 
} 
+0

Я думаю, что это статическое ключевое слово, которое решает это. Я прав? – Nikola

+1

Нестатические синхронизированные методы синхронизируются по внутренней блокировке заданного * экземпляра * (т. Е. 'Cell' или' othercell' - два разных объекта имеют два замка, которые могут быть получены параллельно). Статические синхронизированные методы синхронизируются с помощью * class * (i. E. 'Cell.class' - вызовы' swapValues ​​() 'должны иметь одну и ту же блокировку, поэтому они выполняются последовательно). –

+0

Я только заметил, что он всегда меняет 15 и 23 дважды и забывает об обратном. – Nikola

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