2016-04-29 6 views
0

Я не пытаюсь заполнить доску другим вопросом, но я прочел около 15 решений, и никто не имеет такой же проблемы. Вот код, который я смотрю на:синхронизированные потоки не блокируют друг друга

private AgentModel agent; 
private UserModel user; 
private int type; 

public AgentThread(AgentModel agent, UserModel user, int type) { 
    this.agent = agent; 
    this.user = user; 
    this.type = type; 
} 

public void start() throws InterruptedException { 
    agent.setT(new Thread(this, agent.getID())); 
    agent.getT().start(); 
} 

И немного вниз путь:

public void run() { 
    while (!agent.getT().isInterrupted()) { 
     agent.nextOP(); 

     try { 
      if (agent.getOPS() > 0) { 
       agent.getT().sleep((long) (1000/agent.getOPS())); 
      } else { 
       agent.getT().sleep(1000); 
      } 
     } catch (InterruptedException e) { 
      // TODO Auto-generated catch block 
      agent.getT().interrupt(); 
     } 
     synchronized (user) { 
      agent.setState(agent.getT().getState().toString()); 
      // System.out.println("Operations Completed: " + 
      // (1+agent.getOPCompleted())); 
      if (type == 3) { 
       user.deposit(agent.getAmount(), Integer.valueOf(agent.getID())); 
      } 
      if (type == 4) { 
       user.withdraw(agent.getAmount(), Integer.valueOf(agent.getID())); 
      } 
     } 
    } 
} 

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

Моя проблема заключается в следующем: я устанавливаю блокировку как экземпляр класса UserModel 'user'. Потоки должны либо сдавать, либо снимать в зависимости от типа своего агента.

Когда я выполняю agent.getT().getState(), он всегда возвращает RUNNABLE независимо от количества экземпляров AgentThread, которые я создал. Каждому AgentThread присваивается новый агент и новый поток, но тот же объект пользователя. Кажется, что нити никогда не блокируют друг друга.

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

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

+0

Есть много кода, который вы не показываете нам, но из любопытства, сколько времени вы ожидаете, что поток потратит на любой проход через этот «синхронизированный» блок? Это может быть всего лишь микросекунды. Вы говорите: «Независимо от того, сколько экземпляров« AgentThread »я создал», но сколько экземпляров? Как часто они входят в блок «synchronized»? И как часто ваша программа запрашивает состояние потока? То, что я на самом деле пытаюсь понять здесь, в чем причина, вы должны думать, что будет так много споров по поводу этой блокировки, что вы, вероятно, заметите это? –

+0

@james large У меня было сразу 4 экземпляра, все быстро вошли в блок, и программа запрашивает состояние потоков каждый проход через блок – BKreger

+0

@mastov, как бы определить, был ли поток заблокирован вне проверки его состояния? – BKreger

ответ

0

Вы только блокируете объект User в течение достаточно времени для выполнения операции депозита() или вывода() с интервалом, вероятно, сотнями миллисекунд. Если депозит() или вывод() не зависят от внешних ресурсов с высокой задержкой, они, вероятно, выполняются на долю микросекунды, что было бы достаточно, например, для тысяч строк кода. В результате ваши шансы поймать систему в состоянии, когда поток имеет заблокированный объект User, вероятно, меньше 1 из 100 000. Кроме того, для того, чтобы другой поток был заблокирован, он также должен был попытаться выполнить операцию депозита() или снятия(). Учитывая ваши вероятные параметры, шансы на такое столкновение составляют менее одного миллиона, что, вероятно, объясняет, почему вы его никогда не видели.

0

Когда я выполняю agent.getT(). GetState(), он всегда возвращает RUNNABLE независимо от количества экземпляров AgentThread, которые я создал.

Право. Это связано с тем, что вы вызываете agent.getT().getState() изнутри самого потока. Нить всегда будет видеть себя как RUNNABLE. Когда он заблокирован или ждет, он не смотрит.

Кажется, что нити никогда не блокируют друг друга.

Нет, поскольку я прочитал код, они, безусловно, блокируют друг друга, если они работают над одним и тем же объектом User. Тем не менее, вы никогда не звоните agent.getT().getState() из другого потока, чтобы он мог видеть состояния или WAITING.

Один из способов взглянуть на поток извне - turning on JMX и использовать jconsole. Если вы перейдете на вкладку «Темы», вы сможете увидеть, что счетчики «Всего заблокированы» и «Всего ожидали» увеличиваются на ваших рабочих потоках.

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

Я предполагаю, что это то, что вы ожидаете.

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