我很难理解synchronized
和重入锁定。这是我正在尝试的小程序:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Reentr {
public static void main(String[] args) {
ExecutorService eService = Executors.newFixedThreadPool(2);
for (int i = 1; i <= 2; i++) {
eService.execute(new process());
}
try {
Thread.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
eService.shutdown();
}
}
class process implements Runnable {
int count = 0;
@Override
public void run() {
processTest();
}
public synchronized void processTest() {
try {
for (int i = 1; i <= 2; i++) {
count += i;
System.out.println("count value for " + Thread.currentThread().getName() + " is " + count);
}
} finally {
System.out.println("count for " + Thread.currentThread().getName() + " is " + count);
}
}
}
输出结果为:
count value for pool-1-thread-2 is 1
count value for pool-1-thread-1 is 1
count value for pool-1-thread-2 is 3
count for pool-1-thread-2 is 3
count value for pool-1-thread-1 is 3
count for pool-1-thread-1 is 3
如果我们在输出中看到两个线程都在同步块中。我的印象是一个线程必须完成synchronized方法的执行,之后其他线程将进入该方法。
理想情况下,我期待结果像这样
count value for pool-1-thread-1 is 1
count value for pool-1-thread-1 is 3
count for pool-1-thread-1 is 3
count value for pool-1-thread-2 is 1
count value for pool-1-thread-2 is 3
count for pool-1-thread-2 is 3
我已使用synchronized块和可重入锁替换了synchronized方法。但是,我仍然有相同的输出。我错过了什么?
答案 0 :(得分:1)
当声明实例方法synchronized
时,它会在对象实例上同步。由于在每次循环迭代中运行new process()
,因此对象实例不同,因此同步毫无意义。尝试创建一个process
对象并将其传递给您开始的两个线程。
当您这样做时,也将count
实例变量移动到processTest
方法中。这样它就是线程安全的。
答案 1 :(得分:1)
您有两个不同的process
实例(作为旁白;您应该始终使用大写字母命名类)。 synchronized
关键字相当于:
public void processTest() {
synchronized(this) {
// etc..
}
}
如果您希望一个线程在另一个线程之后运行,则它们必须在同一个对象上同步。如果您这样做,例如:
class process implements Runnable {
// note that this is static
private static final Object lock = new Object();
public void processTest() {
synchronized(lock) {
// your code
}
}
}
然后你的代码会有一个线程在另一个之后运行。另一种方法是将锁传递给Object
构造函数,或Semaphore
的相同实例等。