当我尝试执行这段代码时,我得到的输出就像12221121212121221212
一样。当我将方法声明为synchronized
时,它不应该允许其他线程接管控件
package com.test;
public class TestProject extends Thread {
public void run() {
synchronized (this) {
for (int i = 0; i < 10; i++) {
System.out.print(getName());
}
}
}
public static void main(String[] args) throws InterruptedException {
TestProject myProject = new TestProject();
TestProject myProject1 = new TestProject();
myProject.setName("1");
myProject1.setName("2");
myProject.start();
myProacject1.start();
}
}
那么,如何更改代码以顺序格式获得 11111111112222222222 或 22222222221111111111 的输出?
答案 0 :(得分:6)
您正在this
上同步,即在TestProject
对象上进行同步。由于您有两个单独的对象,因此您有两个单独的锁。因此,无论其他线程正在做什么,两个线程都可以进入synchronized
部分。
要在TestProject
的实例之间进行同步,您需要一个静态锁:
public class TestProject extends Thread {
private static final Object lock = new Object();
public void run() {
synchronized (lock) {
...
答案 1 :(得分:1)
Java默认使用偏向锁定。这意味着锁将有利于最后一个线程访问锁。如果你认为一个线程可以在另一个线程开始之前启动,运行并完成,那么我希望你能让一个线程在大部分时间开始运行之前完成。
我刚注意到你在循环外锁定。这将保证您在另一个线程开始之前运行一个线程。
这是强制公平交替线程的方法。
public class TestProject implements Runnable {
private final Lock lock;
public TestProject(Lock lock) {
this.lock = lock;
}
public void run() {
for (int i = 0; i < 10; i++) {
lock.lock();
try {
System.out.print(Thread.currentThread().getName());
} finally {
lock.unlock();
}
}
}
public static void main(String... ignored) {
Lock lock = new ReentrantLock(true);
new Thread(new TestProject(lock), "1").start();
new Thread(new TestProject(lock), "2").start();
}
}
可以打印
12121212121212121212
注意:如果您使锁定不公平,您可以获得(将true更改为false)
11111111112222222222
注意:如果你想在两个任务之间进行公平的交替,那么使用一个线程和一个循环要简单得多。
public static void main(String... ignored) {
for (int i = 0; i < 10; i++) {
// task 1
System.out.print("1");
// task 2
System.out.print("2");
}
}
答案 2 :(得分:0)
你也可以在myProject1上使用join方法,以便等待另一个线程完成
答案 3 :(得分:0)
以下方法可用于实现线程之间的同步
1)。使用静态全局锁并将该对象变量作为参数传递给synchronized块
2)。使用join()
3)。为Object类创建一个实例,并将其作为参数传递给synchronized块,如此Object myObject = TestProject.class
现在将myObject传递给synchronized块
使用上述任一方式我们都可以实现同步