如何在以下环境中确保线程安全?

may*_*ran 4 java multithreading locking timer reentrantlock

我有一个名为processOutbox的方法.我希望它是线程安全的.当一个线程在它时,我不希望另一个线程调用此方法.我已经按照以下方式实现了它.我做得对吗?我的实施有漏洞吗?如果有,请告知我如何解决它.

this.start();
    outboxLock.lock();
    timer = new Timer();
    try{
    timer.scheduleAtFixedRate(new TimerTask() {
            public void run() {
               processOutbox();
            }
        }, 0, period);
    } finally{
        outboxLock.unlock();
    }
Run Code Online (Sandbox Code Playgroud)

Dav*_*ero 5

如果要创建方法processOutbox,则应使用关键字synchronized:

public class YourClass{
    public synchronized void processOutbox(){
         //do all you want
    }
}
Run Code Online (Sandbox Code Playgroud)

更多信息:https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html

如果您的代码中有一个YourClass实例被调用myInstance,那么所有调用都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();
Run Code Online (Sandbox Code Playgroud)

这里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();
Run Code Online (Sandbox Code Playgroud)

thead2 不会等待,因为他们在不同的实例上调用该方法.

有人特别询问有关使用ReentrantLock的问题 - 所以我将这个回复添加到这个,因为这个是正确的.

public class YourClass {
    private Lock outboxLock = new ReentrantLock();
    public void processOutbox() {
        outboxLock.lock()
        try {
            // do stuff
        } finally {
            outboxLock.unlock()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我特别提到这一点是因为你也可以做一些事情,你可以将其他线程保持在锁定之外,而不是通过使用tryLock来阻止它们.

public class YourClass {
    private Lock outboxLock = new ReentrantLock();
    public void processOutbox() {
        if( outboxLock.tryLock() ) {  
            try {
                // do stuff
            } finally {
                outboxLock.unlock()
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)