2016-08-22 5 views
1

Итак, на Java я знаю, что вы можете использовать так называемую «внутреннюю блокировку» объектов для создания областей взаимного исключения, а также для обеспечения видимости памяти. Java делает его особенно легко неявным замок на внутренней замке this объекта с некоторыми синтаксическими как:Можно ли использовать встроенную блокировку объекта Thread в Java?

public class Foo{ 
    public synchronized doFoo(){ 
     //doFoo is executed in an implicit synchronized block 
     //on the 'this' object 
    } 
} 

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

public class Bar extends Thread{ //notice the 'extends Thread' here 
    public synchronized doBar(){ 
     //doBar is executed in an implicit synchronized block 
     //on the 'this' object 
    } 
} 

В настоящем время, я буду придерживаться чего-то я знаю, является более безопасным, например:

public class Baz extends Thread{ //notice the 'extends Thread' here 
    private final Object explicitLockObject = new Object(); 

    public doBaz(){ 
     synchronized(explicitLockObject){ 
      //doBaz impl 
     } 
    } 
} 

Моих проблемы были бы два раза с опцией # 2 (Bar примера):

  1. есть ли существующий код JVM или Java конвенции о синхронизации на резьбе, которые могут вступать в противоречие с такой блокировками?
  2. Блокировка на this обычно подразумевает, что доступ к этому объекту всегда должен быть защищен встроенной блокировкой этого объекта. В случае потока Bar это означает, что мы подразумеваем, что в любое время, когда вы касаетесь нити Bar, вы должны синхронизировать экземпляр. Кажется, что это может привести к тому, что некоторые другие потоки будут блокироваться без необходимости (или даже опасно) до тех пор, пока Bar не завершит/не удалит.

Являются ли вышеприведенные проблемы? Я чувствую, что нужен маяк Брайан Гетц для этого :-)

+3

1. Ну, есть соглашение, в котором вы не должны распространять «Thread» в первую очередь: реализовать «Runnable», передать его в «Thread» как параметр конструктора (см. [Этот вопрос] (http : //stackoverflow.com/questions/541487/implements-runnable-vs-extends-thread)). Теперь вы беспокоитесь о синхронизации на «Runnable»? –

+0

Да, я знаю об этом соглашении. Честно говоря, это не изначально мой код, и я не планирую рефакторинг. Я знаю, что «Runnable» будет в порядке, поскольку он не поставляется с государственным багажом. Но увы! Это не то, что у меня есть, и мне любопытно узнать ответ на этот вопрос. – codeCogs

+1

Я бы рекомендовал, чтобы разработчики предпочитали новые классы в пакете параллелизма и не использовали необработанные потоки. Многопоточный код достаточно прост для записи. – duffymo

ответ

2

... есть какие-то причины, чтобы избежать [блокировки на Thread например]?

Так что, если вы посмотрите на Thread класса, вы можете видеть, что есть целый ряд экземпляров synchronized методов. Они включают в себя:

  • start()
  • stop() (устаревшее)
  • join(long) (который вызывается из join())
  • join(long, int)

Это кажется, что это может в конечном итоге вызывает некоторые другие (или даже опасно) до Bar завершает/завершает работу.

Правильно, поэтому любой, кто вызывает вышеуказанные методы, блокирует другие методы synchronized. Очевидно, что только методы join(...) будут проблемой, и они должны вернуться до тех пор, пока Thread не закончится.

Как указано в javadocs for Thread.join(...):

В поток завершается метод this.notifyAll() вызывается. Рекомендуется, чтобы приложений не использовали wait(), notify(), или notifyAll() на Thread экземпляров.

Я не вижу предупреждений о synchronized в любом месте Thread источник.

Также быстрый взгляд через ThreadPoolExecutor показывает, что по крайней мере, не synchronize на Runnable или Callable экземпляров, которые были бы очень плохо, так что, по крайней мере со стандартным ExecutorService вы должны быть хорошо.

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

Надеюсь, это поможет.

+1

Очень полезно - я бы рассмотрел предупреждения о 'wait()', 'notify()' и т. Д., Чтобы быть свидетельством того, что использование многопоточных утилит объекта 'Thread' немного отличается от использования любого другого« объекта », но отсутствие предупреждения о внутреннем мониторе само по себе свидетельствует о том, что он должен быть в порядке. Приобретенный, но я оставлю еще несколько дней, чтобы кто-то набросился на какой-то источник/аргумент, который окончательно решает проблему, а не полагается на отсутствие предупреждения (когда документы полностью завершены :-)?). Если скоро никто не прыгнет, я отвечу. – codeCogs

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