Синхронизированные методы и блокировки объектов - PullRequest
0 голосов
/ 02 февраля 2019

Из того, что я прочитал и понял, каждый объект имеет блокировку, которая происходит, когда он пытается получить доступ к синхронизированному методу.Вот мой код (в 2 разных файлах классов):

public class test {

 public synchronized void inc1( String who ) {

         for( int i = 0 ; i < 1500 ; i++ )
             System.out.println( who+": "+i );
 }
}



public class testsyn implements Runnable {

    test k = new test( );

    public static void main( String[ ] args )
    {

        new Thread( new testsyn( ) ).start( );

        new testsyn( ).doStuff( );

    }

    public void doStuff( ) { k.inc1( "Main" ); }

    public void run( )
    {
        k.inc1( "Thread" );
    }
}

Итак, давайте предположим, что первая строка моего вывода: "Main: 0".это означает, что основной поток получил ключ для тестового объекта с именем 'k', верно?чем возможно, что другой созданный мной поток может получить доступ к методу "inc1" и распечатать вывод до того, как основной поток завершит его?

Я заметил, что эта проблема возникает в этом конкретном шаблоне, ноесли бы я сделал статический 'k' и написал бы вместо этого (в классе testsyn):

public class testsyn implements Runnable {

    static test k = new test( );

    public static void main( String[ ] args )
    {

        new Thread( new testsyn( ) ).start( );

        k.inc1( "Main" );

    }


    public void run( )
    {
        k.inc1( "Thread" );
    }
}

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

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

Ответы [ 2 ]

0 голосов
/ 03 февраля 2019

Итак, предположим, что первая строка моего вывода: «Main: 0».это означает, что основной поток получил ключ для тестового объекта с именем 'k', верно?чем возможно, что другой созданный мною поток сможет проникнуть внутрь метода "inc1" и распечатать вывод до того, как основной поток завершит его?

Вы пишете "тестовый объект с именем 'к '", как будто был только один.В вашем примере k является переменной экземпляра класса testsyn, поэтому каждый экземпляр имеет свою собственную.Они ссылаются на разные объекты, каждый со своим монитором.Таким образом, поток, выполняющий метод синхронизированного экземпляра одного из этих объектов, не препятствует другому потоку выполнять метод синхронизированного экземпляра другого.

, если бы я сделал 'k' статическим [...] между выходом не было бы столкновения.

Да.static переменные относятся к классу, в котором они объявлены.Их разделяют все экземпляры.Статический k, инициализированный до запуска main() и не изменяемый после этого, используется обоими потоками.Поскольку они оба пытаются запустить синхронизированный метод одного и того же объекта , нужно дождаться окончания работы другого.

0 голосов
/ 02 февраля 2019

Да, ключевое слово synchronized используется для получения блокировки;блокировка связана с экземпляром объекта.У вас есть два экземпляра класса test;по одному для каждой темы.Так что нет споров.Если поле k является статическим, тогда один поток совместно используется потоками.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...