我正在尝试了解java中的同步。我有以下例子,
public class TestThr implements Runnable {
public static void main(String[] args) {
Thread t=new Thread(new TestThr());
Thread t1=new Thread(new TestThr());
t.start();
t1.start();
}
@Override
public void run() {
sync();
}
public synchronized void sync(){
for (int i=0;i<10;i++){
System.out.println("Running "+Thread.currentThread().getName());
}
}
}
Output : Running Thread-0 Running Thread-1 Running Thread-0 Running Thread-1 Running Thread-0 Running Thread-1 Running Thread-1 Running Thread-1 Running Thread-0 Running Thread-1 Running Thread-1 Running Thread-1 Running Thread-1 Running Thread-1 Running Thread-0 Running Thread-0 Running Thread-0 Running Thread-0 Running Thread-0 Running Thread-0
从上面的例子中,我期待一个线程(无论谁进入第一个)将完成迭代,然后第二个将开始并完成但是我的输出不一致。
请添加您的意见。
提前致谢。
答案 0 :(得分:4)
从上面的例子中我期待一个线程(无论谁先进入)将完成迭代,然后第二个将开始并完成,但我得到的输出不一致。
您获得的输出不是您理解的,但它与您编写的代码一致。当您使用synchronized
方法时,您将锁定封闭类的实例。
public class TestThr implements Runnable {
...
public synchronized void sync() {
在您的示例中,sync
方法为synchronized
,因此它将锁定TestThr
的特定实例。你正在开始你的线程:
Thread t = new Thread(new TestThr());
Thread t1 = new Thread(new TestThr());
这意味着每个线程都有自己的TestThr
实例,因此它们会锁定不同的实例,并且不会相互阻止运行。
如果您改为执行以下操作:
final TestThr testThr = new TestThr();
Thread t = new Thread(testThr);
Thread t1 = new Thread(testThr);
现在,2个线程正在TestThr
的同一个实例上工作,因此它们将锁定在同一个对象上,输出将是您所期望的。
这仅适用,因为TestThr
没有任何存储的字段。如果你需要一个更复杂的类,那么我将一个锁对象传递给它们。类似的东西:
final Object lockObject = new Object();
Thread t = new Thread(new TestThr(lockObject));
Thread t1 = new Thread(new TestThr(lockObject));
然后在你的代码里面你会这样做:
public void sync() {
synchronized (lockObject) {
...
因此该方法不会被锁定,而是您将在共享锁对象上进行同步。
顺便说一下,考虑到循环的大小,很可能一个线程可能启动并运行循环,然后在另一个线程开始之前退出。使用System.out.println(...)
调用会降低线程速度,因此可能会引发争用,但如果删除输出则需要担心。由于线程之间的竞争条件,可能很难测试这样的线程程序。
答案 1 :(得分:3)
这是:
abcdefghij[enter]
的工作原理如下:
public synchronized void sync(){
for (int i=0;i<10;i++){
System.out.println("Running "+Thread.currentThread().getName());
}
}
因此,在您的情况下,每个线程由不同的 public void sync(){
synchronize(this) {
for (int i=0;i<10;i++){
System.out.println("Running "+Thread.currentThread().getName());
}
}
}
对象同步:
要查看预期输出,您可以尝试下一步:
TestThr
答案 2 :(得分:1)
正如@Pavlo Plynko所写,您使用的是synchronized方法,但是您为Thread创建了两个不同的对象。您应该创建单个实例,然后将此对象提供给您的线程。在这种情况下,两个线程将使用相同的object实例,并等待执行相同的方法。
以下代码:
public class TestThr implements Runnable {
public static void main(String[] args) {
TestThr synchronizedObject = new TestThr();
Thread t = new Thread(synchronizedObject);
Thread t1 = new Thread(synchronizedObject);
t.start();
t1.start();
}
@Override
public void run() {
System.out.println("Thread " + Thread.currentThread().getName() + " is waiting for execution");
sync();
System.out.println("Thread " + Thread.currentThread().getName() + " has executed synced method");
}
public synchronized void sync() {
for (int i = 0; i < 10; i++) {
System.out.println("Running " + Thread.currentThread().getName());
}
}
}
将提供以下输出:
Thread Thread-0 is waiting for execution
Thread Thread-1 is waiting for execution
Running Thread-0
Running Thread-0
Running Thread-0
Running Thread-0
Running Thread-0
Running Thread-0
Running Thread-0
Running Thread-0
Running Thread-0
Running Thread-0
Thread Thread-0 has executed synced method
Running Thread-1
Running Thread-1
Running Thread-1
Running Thread-1
Running Thread-1
Running Thread-1
Running Thread-1
Running Thread-1
Running Thread-1
Running Thread-1
Thread Thread-1 has executed synced method