Синхронизация экземпляров

1

Я написал небольшой блок кода, чтобы понять понятия synchronized блоков:

public class ObjectLevelSynchronized {

    public void run() {
        synchronized(this) {
            try {
                System.out.println(Thread.currentThread().getName());
                Thread.sleep(100);
                System.out.println(Thread.currentThread().getName() + " Finished.");
            }catch(Exception e) {

            }
        }
    }

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

        final ObjectLevelSynchronized c = new ObjectLevelSynchronized();
        final ObjectLevelSynchronized c1 = new ObjectLevelSynchronized();       

        Thread t = new Thread(new Runnable() {
            public void run() {
                c.run();
                c.run();
            }
        }, "MyThread1");

        Thread t1 = new Thread(new Runnable() {
            public void run() {
                c1.run();
                c1.run();
            }
        }, "MyThread2");

        t.start();
        t1.start();
    }
}

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

Ожидаемый результат:

MyThread1
MyThread2
MyThread1 Finished
MyThread2 Finished
MyThread1
MyThread2 
MyThread1 Finished
MyThread2 Finished

Фактический результат

MyThread1
MyThread1 Finished.
MyThread1
MyThread1 Finished.
MyThread2
MyThread2 Finished.
MyThread2
MyThread2 Finished.

Почему synchronized блок заблокировал код для двух разных объектов?

  • 1
    Вы имели в виду ObjectLevelSynchronized вместо ClassLevelSynchronized в основном методе?
Теги:
multithreading
synchronized

3 ответа

0
Лучший ответ

у вас есть два разных замка.

вы используете synchronized(this)

и вы создаете два объекта

final ClassLevelSynchronized c = new ClassLevelSynchronized();
final ClassLevelSynchronized c1 = new ClassLevelSynchronized();     

поэтому c и c1 - ваши блокировки, и синхронизация просматривает эти блокировки. вы должны использовать тот же объект для синхронизации блока. Самый простой способ для вас:

private static Object lock = new Object();

и использовать его в синхронизированном

synchronized(lock)

или, для вашего вывода, это тоже должно работать.

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

        final ObjectLevelSynchronized c = new ObjectLevelSynchronized();
        final ObjectLevelSynchronized c1 = new ObjectLevelSynchronized();       
        final Object lock = new Object();
        Thread t = new Thread(new Runnable() {
            public void run() {
                synchronized (lock) {
                    c.run();
                    c.run();
                }
            }
        }, "MyThread1");

        Thread t1 = new Thread(new Runnable() {
            public void run() {
                synchronized (lock) {
                    c1.run();
                    c1.run();
                }
            }
        }, "MyThread2");

        t.start();
        t1.start();
    }
  • 0
    Я думаю, что он хочет иметь две блокировки, а не одну, но при этом ведет себя как использование одной блокировки и спрашивает, почему она не действует как две блокировки.
  • 0
    но он спросил: «Почему синхронизирован блок, заблокирован код для двух разных объектов?». на самом деле, как вывод, не нужен уже ни один блок синхронизации. Достаточно просто вызвать функции запуска по порядку.
0

Мой результат следующий, как вы ожидали:

MyThread2
MyThread1
MyThread2 Finished.
MyThread2
MyThread1 Finished.
MyThread1
MyThread2 Finished.
MyThread1 Finished.

При тестировании многопоточных программ всегда выполняйте несколько прогонов, потому что вывод не всегда одинаковый, потому что порядок выполнения может отличаться.

0

Предполагая, что тип ObjectLevelSynchronized, на основе кода, который вы поделили, не обязательно, чтобы программа ObjectLevelSynchronized результат так же, как вы делились, так как no mechanism для связи между двумя экземплярами созданных вами объектов и выполняться в разных потоки. Во-вторых, порядок инструкций Sysout основан исключительно на усмотрении JVM/OS, т.е. Один из T1 и T2 может работать первым. Поэтому для того, чтобы распечатать то, как вы ожидали, вам нужно связаться с другими экземплярами, кто должен печатать первые или простые слова, для которых требуется блокировка для совместного использования между этими двумя объектами, которые выполняются в потоках

Ещё вопросы

Сообщество Overcoder
Наверх
Меню