繁体   English   中英

同步块程序结果与同步方法不同

[英]Sysnchronized block program results are different from synchronized method

我已经通过锁定.class在同步块上编写了一个程序,并且我的程序正在逐线程执行。 但是,当我使用同步方法编写相同的代码时,输​​出完全不同。

同步块程序如下:

public class SyncBlock {
    public static void main(String[] args) {
        final Thread t1 = new SimpleThread("First Thread");
        final Thread t2 = new SimpleThread("Second Thread");
        t1.start();
        t2.start();
    }
}

class SimpleThread extends Thread {
    public SimpleThread(String str) {
        super(str);
    }

    public void run() {
        synchronized (SyncBlock.class) {
            for (int i = 0; i < 5; i++) {
                System.out.println(getName() + " says " + i);
                try {
                    sleep((long) (Math.random() * 1000));
                } catch (InterruptedException e) {
                }
            }
            System.out.println(getName() + " is done.");
        }
    }
}

输出是:

First Thread says 0
First Thread says 1
First Thread says 2
First Thread says 3
First Thread says 4
First Thread is done.
Second Thread says 0
Second Thread says 1
Second Thread says 2
Second Thread says 3
Second Thread says 4
Second Thread is done.

现在我正在使用同步方法使用相同的程序。 但是它的行为有所不同。 您能否解释一下两者的行为是否不同,或者是否有使用同步块和同步方法获得相同输出的解决方案?

使用同步方法:

现在同步运行方法并替换以下代码:

public synchronized void run() {
            for (int i = 0; i < 10; i++) {
                System.out.println(getName() + " says " + i);
                try {
                    sleep((long) (Math.random() * 1000));
                } catch (InterruptedException e) {
                }
            }
            System.out.println(getName() + " is done.");
}

这里的输出是不同的:

First Thread says 0
Second Thread says 0
Second Thread says 1
First Thread says 1
First Thread says 2
Second Thread says 2
First Thread says 3
Second Thread says 3
First Thread says 4
First Thread is done.
Second Thread says 4
Second Thread is done.

synchronized块中,您正在锁定类对象,当一个对象调用它时,该类对象将在其他对象上锁定run方法的执行。 但是,当您synchronized运行方法时,您将锁定对象而不是类,因此它将不会阻止另一个线程在另一个对象上执行相同的方法。 因此,两个线程并行执行。

如果要实现与synchronized块相同的执行,则可以有一个synchronized static方法,该方法执行正在运行的步骤并从run方法中调用它

当您使用: synchronized (SyncBlock.class) ,您的代码可以正常工作,因为您锁定了SyncBlock类,因此其他线程无法访问SyncBlock Object类,直到第一个线程释放它。

在第二种情况下,您锁定了SimpleThread的当前实例(此),两个线程的锁定将不同(您锁定了SimpleThread实例本身)。 因此,锁本身是无效的,JVM也可能会删除同步代码(从jdk6 U23-引入转义分析来优化此类事情)

如果是同步块,则说第一个线程先进入

synchronized (SyncBlock.class) {-->  // here First thread takes the lock now  no other thread can enter 

现在,当第一个线程到达此处

  System.out.println(getName() + " is done.");
    } --->  here First thread releases the lock  . So this gives chance to other thread which are waiting for this lock . so in ur case Second thread takes it and then executes it and when it reaches here it will release and then again other thread can take over. Note  : This behavior is not definite 

线程可以任何方式执行取决于CPU调度策略

在同步方法中发生的事情是,一旦一个线程进入该方法,它将完成其任务,然后释放锁。在另一个线程获得执行机会之后。

另请注意, 睡眠不会释放LOCK 在那个阶段线程处于等待状态

这里没有其他答案是错误的,但是它们都没有真正说明问题的核心。

当您编写synchronized ,您的代码将在一个对象上同步,并且JVM保证不能在同一对象上同时同步两个线程。

在第一个示例中,SimpleThread.run()方法在唯一的SyncBlock类对象上同步。 这样可以防止两个线程同时进入run(),因为它们都试图在同一个对象上进行同步:只有一个SyncBlock类对象。

在第二个示例中,SimpleThread.run()方法在this同步。 并不妨碍两个线程在同一时间进入运行(),因为两个线程同步在两个不同的对象:创建SimpleThread的两个实例。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM