2015-04-07 4 views
1

Я хотел бы решить взаимное исключение с помощью функции Swap, но программа страдает от тупика, и я не знаю почему. Кажется, что проблема возникает, когда поток выполняется два раза подряд.Java - тупик с использованием функции SWAP для решения взаимного исключения

свопа замка логик:

Каждого поток делает использование локальной переменной и совместно переменным. Поток сначала блокирует его local переменная (например, предположим, что значение 1). Когда поток локальная переменная разблокирован (например, предположим, значение 0), она может выполнить критическую секцию, если нить локальная переменная блокируется (например, предположим, значение 1) нить в занят ожидающего (занято ожидание проверяет локальную переменную разблокировку и вызывает свопа функции)

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

Когда своп потока вызовов, если эти «общие» переменные 0 (разблокировать) после обмена мы имеем, что общих переменная 1 и местных 0. Таким образом, только этот поток может получить доступ к критический раздел нет.

В конце (не более критической секции) нить разблокирует общую переменную.

Главная

public class Mutex { 

    public static void main(String []args){ 
     LockVar var = new LockVar(0); 
     ThreadSwap th0 = new ThreadSwap(var); 
     ThreadSwap th1 = new ThreadSwap(var); 
     ThreadSwap th2 = new ThreadSwap(var); 
     th0.start(); 
     th1.start(); 
     th2.start(); 
    } 
} 

Класс Thread (Логика этого типа мьютекса подчеркивается)

class ThreadSwap extends Thread{ 

    private LockVar shared_var; 

    public ThreadSwap(LockVar var){ 
    this.shared_var = var; 
    } 
    @Override 
    public void run(){ 
     LockVar local = new LockVar(1); 
     while(true){ 
     ---> local.setVar(1); 
     ---> while(local.getVar() == 1){Synch.SWAP(shared_var, local);} 
      System.out.println("Thread " + getId() + " exec critical section."); 
      // Critical section 
      System.out.println("Thread " + getId() + " is leaving critical section."); 
     ---> shared_var.setVar(0); 
     } 
    } 
} 

функции Обмена

class Synch{ 
public static synchronized void SWAP(LockVar shared, LockVar local){ 
    int temp = shared.getVar(); 
    shared.setVar(local.getVar()); 
    local.setVar(temp); 
} 
... 
} 

Общий вар Класс

class LockVar{ 
private volatile int var; 
public LockVar(int value){ 
    this.var = value; 
} 
public int getVar(){ 
    return this.var; 
} 
public void setVar(int value){ 
    this.var=value; 
} 

}

+1

Что такое ThreadTaS? – user2891462

+0

Каков ожидаемый результат? Каков фактический результат, который вы получаете? Обратите внимание, что вы используете setVar в конце каждого цикла несинхронизированным образом. – user2891462

+0

Извините, что я отредактирую правильный код. – MadDogTannen

ответ

0

Представьте себе такой сценарий:

  1. Первые нити свопы местной и shared_var. Теперь shared_var равен 1, а local равен 0.
  2. Поскольку синхронизация по SWAP находится в классе Synch, как только первый поток выполняется с помощью SWAP, Thread 2 может войти в него. Thread 2 делает temp = 1, и в этот момент монитор переключается обратно в Thread 1.
  3. Thread 1 завершает первую итерацию цикла, печатает сообщения exec и выходит из критической секции и устанавливает shared_var = 0. Монитор перемещается в Тема 2.
  4. Резьба 2 продолжается с помощью SWAP. где он его оставил. Он выполняет shared.setVar(local.getVar()); (теперь shared_var == 1) и local.setVar(temp); (помните, что temp равен 1 из шага 2).

Создан тупик: shared_var равен 1 и нить не находится в критическом разделе. Это связано с тем, что SWAP не является атомарным (монитор может отходить от потока, выполняющего синхронизированный метод, он просто не разрешает другим потокам вводить такой метод, а другие методы не синхронизируются на одной и той же блокировке (класс в случае статического метода , экземпляр объекта в случае нестатического метода)).

Чтобы исправить это, вы не должны разрешать совместное использование во время выполнения SWAP, найдя способ сделать его атомарным. Возможность была бы избавиться от локальных и использовать на AtomicBoolean, которые в настоящий момент будут играть роль shared_var.

Атомные типы гарантируют атомарность и волатильность (см. documentation). Таким образом, каждый поток должен получить ссылку (простите за вольную номенклатуру) к AtomicBoolean используется для сигнализации и использовать compareAndSet атомарно изменить значение переменного таким образом, что видно сразу к другим потокам:

import java.util.concurrent.atomic.AtomicBoolean; 

public class Mutex { 

    public static void main(String []args){ 
    AtomicBoolean isLocked = new AtomicBoolean(false); 
    ThreadSwap th0 = new ThreadSwap(isLocked); 
    ThreadSwap th1 = new ThreadSwap(isLocked); 
    ThreadSwap th2 = new ThreadSwap(isLocked); 
    th0.start(); 
    th1.start(); 
    th2.start(); 
    } 
} 

class ThreadSwap extends Thread { 

    private AtomicBoolean shared_IsLocked; 

    public ThreadSwap(AtomicBoolean var){ 
    this.shared_IsLocked = var; 
    } 

    @Override 
    public void run(){ 
    while(true){ 
     // While the flag is true (locked), keep checking 
     // If it is false (not locked), atomically change its value and keep going 
     while(!shared_IsLocked.compareAndSet(false, true)); 
     System.out.println("Thread " + getId() + " exec critical section."); 
      // Critical section 
     System.out.println("Thread " + getId() + " is leaving critical section."); 
     shared_IsLocked.set(false); 
    } 
    } 
} 
+0

Большое спасибо, вы поможете мне улучшить мои знания о мониторе. Таким образом, это решение: ** Класс резьбы ** ... ... ... Synch.SET (shared_var, 0); ... ** Synch Class ** класс 'Synch { общественного синхронизируется статической силы SET (LockVar совместно, внутр значение) { shared.setVar (значение); } public synchronized static void SWAP (LockVar shared, LockVar local) { int temp = shared.getVar(); shared.setVar (local.getVar()); local.setVar (температура); } ' – MadDogTannen