Java 实例同步

Java 实例同步,java,multithreading,synchronized,Java,Multithreading,Synchronized,我写了一小段代码来理解synchronized块的概念: public class ObjectLevelSynchronized { public void run() { synchronized(this) { try { System.out.println(Thread.currentThread().getName()); Thread.sleep(100);

我写了一小段代码来理解
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
为两个不同的对象锁定代码?

我的结果如下所示:

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

测试多线程程序时,请始终尝试多次运行,因为输出并不总是相同的,因为执行顺序可能不同。

您有两个不同的锁

您可以使用
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();
    }

假设类型为
ObjectLevelSynchronized
,基于您共享的代码,程序将以您共享的方式输出结果不是强制性的,因为在您创建并在不同线程中运行的对象的两个实例之间没有通信机制。其次,Sysout语句的顺序完全基于JVM/OS的判断,即T1和T2都可以先运行。所以为了按你所期望的方式打印出来,您必须与其他实例沟通谁应该首先打印,或者简单地说,您需要在线程中运行的这两个对象之间共享一个锁

您的意思是ObjectLevelSynchronized,而不是main方法中的ClassLevelSynchronized?我想他想要两个锁而不是一个锁,但是得到的行为就像使用一个锁,并询问为什么它不像拥有两个锁。但他问“为什么同步块,锁定两个不同对象的代码?”。实际上,作为输出,它不需要任何同步块。只要按顺序调用run函数就足够了