如何使这个线程安全

时间:2015-02-10 16:05:50

标签: java multithreading

我一直在阅读很多关于线程的内容,但我不确定处理这种情况的正确方法。假设我有一个引用对象的实用程序类。实用程序类可以处理对象,可以从多个线程调用它

  class Utility{
     Foo xx;
     public Utility(Foo xx){
         this.xx = xx;
     }

    public void doWork(){
       x.action();
    }
  }

现在,如果我有两个线程将访问实用程序类并调用doWork(),其中xx将始终引用同一个对象,我该如何使其线程安全?

编辑:实用程序类有2个实例(每个线程一个),但引用的xx对象相同。请参见编辑:

public class ThreadSafety {

    public static void main(String[] args) throws InterruptedException {
        Foo xx = new Foo();
        Utility util1 =  new Utility(xx); 
        Utility util2 =  new Utility(xx); 
        Thread t1 = new Thread(new MyRunnable(util1) , "t1");
        Thread t2 = new Thread(new MyRunnable(util2) , "t2");

        t1.start();
        t2.start();
        t1.join();
        t2.join();

    }

}

class MyRunnable implements Runnable{
    Utility util;

    @Override
    public void run() {
        util.doWork();
    }


    private void MyRunnable (Utility util) {
        this.util = util;
    }

}

5 个答案:

答案 0 :(得分:3)

Java有一个synchronized关键字,您可以在这种情况下使用它。

public synchronized void doWork() 

<强>读

答案 1 :(得分:3)

public class Utility{
  private final Foo xx;

  public Utility(Foo xx){
    this.xx = xx;
  }

  public void doWork() {
    // ensures only one thread can be calling action
    synchronized(xx) {
      xx.action();
    }
  }
}

以下几点变化:

  1. 制作xx finalprivate。使其private强制控制如何访问xx
  2. 在致电synchronize之前,xx上的
  3. doWork。您可以将synchronized放在方法声明中,但我更愿意明确您要锁定的对象。请注意,这不是“同步xx”。它只使用xx作为锁。在访问可能存在危险的代码块的任何地方,必须使用具有相同监视器对象的synchronized块。

答案 2 :(得分:2)

您可以使用synchronized关键字。

 public synchronized void doWork(){
       x.action();
    }

这将使方法线程安全。有关Oracle documentation上的同步方法的更多信息。

使用更新后的问题: 使用静态方法作为synchronized,然后锁将在不在单个对象上的类上。

答案 3 :(得分:2)

以下是另一种建议:使用synchronized。使用synchronized的代码往往很复杂,错误,无法测试。你会遇到问题,你永远不会知道什么时候会爆炸,即使它有效,你也可能会遇到糟糕的表现。这样做:

创建一个不可变类,您将调用Message来在线程之间进行通信,并使用BlockingQueue Message其他线程存储的消息由你的主线程处理。然后,在主线程中,只需从队列中弹出消息并处理它们。简单(* 1),简单,可测试,万无一失。

BlockingQueue是使用synchronized在内部实现的,它是由知道自己在做什么的人编写的,并且已经过全面测试,因此可行。这是唯一应该包含synchronized的地方。

(* 1)起初看起来似乎并不像在一些地方粘贴synchronized关键字那么容易,但事实上,从长远来看,synchronized总是会出现比起最初似乎要复杂得多,难以做到。

答案 4 :(得分:2)

如果您要更改数据,请考虑使用不可变对象,而不仅仅是简单地使用synchronized关键字。