我有一个名为processOutbox的方法。我希望它是线程安全的。当一个线程在它时,我不希望另一个线程调用此方法。我已经按照以下方式实现了它。我做得对吗?我的实施有漏洞吗?如果有,请告知我如何解决它。
this.start();
outboxLock.lock();
timer = new Timer();
try{
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
processOutbox();
}
}, 0, period);
} finally{
outboxLock.unlock();
}
答案 0 :(得分:5)
如果您想制作方法processOutbox,则应使用关键字synchronized
:
public class YourClass{
public synchronized void processOutbox(){
//do all you want
}
}
更多信息:https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html
如果您的代码中有一个名为myInstance
的YourClass实例,则对processOutbox()
的所有调用都将是线程安全的,因为它们将在实例级别被锁定。
例如:
YourClass myInstance = new YourClass();
Thread thread1 = new Thread(){
public void run(){
myInstance.processOutbox();
}
}
Thread thread2 = new Thread(){
public void run(){
myInstance.processOutbox();
}
}
thread1.start();
thread2.start();
这里thead2将一直等到thread1完成对“processOutbox”
的调用但是例如:
YourClass myInstance = new YourClass();
YourClass myInstance2= new YourClass();
Thread thread1 = new Thread(){
@Override
public void run(){
myInstance.processOutbox();
}
};
Thread thread2 = new Thread(){
@Override
public void run(){
myInstance2.processOutbox();
}
}
thread1.start();
thread2.start();
thead2将 NOT 等待,因为他们在不同的实例上调用该方法。
有人特别询问使用ReentrantLock - 所以我在这个问题上添加了这个回复,因为这个是正确的。
public class YourClass {
private Lock outboxLock = new ReentrantLock();
public void processOutbox() {
outboxLock.lock()
try {
// do stuff
} finally {
outboxLock.unlock()
}
}
}
我特别提到这一点,因为你也可以做一些事情,你可以通过使用tryLock将其他线程从锁定中移除而不会阻止它们阻塞。
public class YourClass {
private Lock outboxLock = new ReentrantLock();
public void processOutbox() {
if( outboxLock.tryLock() ) {
try {
// do stuff
} finally {
outboxLock.unlock()
}
}
}
}
答案 1 :(得分:1)
使用CountDownLatch
进行同步。