我通过锁定.class在同步块上编写了一个程序,我的程序正在逐个线程地执行。但是当我使用synchronized方法编写相同的代码时,输出完全不同。
下面给出的同步块程序:
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.
现在我使用同步方法使用相同的程序。但它表现不同。你能否解释两者的表现是否会有所不同,或者是否有使用同步块和方法获得相同输出的任何解决方案。
使用同步方法:
现在同步run方法并替换此代码:
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.
答案 0 :(得分:4)
在synchronized
块中,您锁定了类对象,当一个对象调用它时,它将锁定run
方法在其他对象上的执行。但是当你synchronized
运行方法时,你将锁定对象而不是类,因此它不会阻止另一个线程在另一个对象上执行相同的方法。因此,两个线程并行执行。
如果要实现与synchronized
块相同的执行,可以使用synchronized static
方法执行运行中的步骤并从run方法调用
答案 1 :(得分:2)
当您使用:synchronized (SyncBlock.class)
时,您的代码正常工作,因为您锁定了SyncBlock类,因此其他线程无法访问SyncBlock
的类Object,直到第一个释放它为止。 / p>
在第二种情况下,您锁定了SimpleThread
(this)的当前实例,两个线程的锁定都不同(您正在锁定SimpleThread实例本身)。所以,锁本身是无效的,JVM也可以删除同步代码(来自jdk6 U23 - 逃逸分析是为了优化这些东西而引入的)
答案 2 :(得分:0)
如果是同步块,则说第一个线程先进入
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 。在那个阶段,线程处于等待状态
答案 3 :(得分:0)
这里没有其他答案是错的,但没有一个真正说明问题的核心。
当你编写synchronized
时,你的代码会在一个Object上同步,而JVM保证不会同时在同一个对象上同步两个线程。
在第一个示例中,SimpleThread.run()方法在唯一的SyncBlock类对象上进行同步。这可以防止两个线程同时进入run(),因为它们都试图在同一个对象上同步:只有一个SyncBlock类对象。
在第二个示例中,SimpleThread.run()方法在this
上同步。这样做 not 阻止两个线程同时进入run(),因为两个线程正在两个不同的对象上进行同步:你创建两个SimpleThread实例。