1

我有这个带有单例模式的示例代码:

class Singleton{
    private static Singleton instance;
  private int count;
  private Singleton(){}
  public static synchronized Singleton getInstance(){
    if(instance==null){
        instance=new Singleton();
    }
    return instance;
  }
  public int getCount(){return count;}
  public void setCount(int count){this.count=count;}
  public static void main(String[] args) throws InterruptedException{
    Thread t1=new Thread(()->{
        while(Singleton.getInstance().getCount()==0){
        //loop
      }
      System.out.println("exist t1 with count="+Singleton.getInstance().getCount());
    });
    t1.start();
    Thread.sleep(1000); //time out to force t1 start before t2
    Thread t2=new Thread(()->{
        Singleton.getInstance().setCount(10000);
    });
    t2.start();
    t1.join();
    t2.join();
  }
}

我有一个问题:在两个线程 t1、t2 中调用的方法getCountsetCount哪个是线程安全的,不是吗?

4

1 回答 1

0

在两个线程 t1、t2 中调用的方法 getCount/setCount 是线程安全的,不是吗?

如果您打算使 t2 所做的更改对 t1可见- 是的,线程 2 设置的计数将对线程 t1 可见。

这是因为线程 1 每次都通过调用getInstancewhich 是一个synchronized方法来获取单例实例。这建立了一个happens-before关系,线程2所做的更改将对线程1可见。


但是,如果您将代码更改为getInstance仅调用一次并将该引用用于 call getCount,则另一个线程 (t2) 所做的更改可能对线程 t1 不可见,并且它可以继续循环。

 Singleton s = Singleton.getInstance();
    while(s.getCount()==0){
        //loop
    }

要使更改得到反映,您必须count进行volatile

private volatile int count;
于 2020-04-05T07:38:41.807 回答