锁定字符串

2个问题:

  1. str字段在A类型的两个实例之间共享[第2行]
  2. 根据以下代码有什么影响?

class A implements Runnable { String str = "hello"; // line 2. public void run(){ Synchronized(str){ System.out.println(str+" "+Thread.currentThread().getName()); Thread.sleep(100); System.out.println(str+" "+Thread.currentThread().getName()); //anything } } public void static main(String[] args){ Thread one = new Thread(new A(),"one").start(); Thread two = new Thread(new A(),"two").start(); } } 

字段本身不在两个实例之间共享。 他们是不同的领域。 但是,它们以相同的值开始,因为字符串文字被实习。

这意味着当synchronized块在一个线程中获取字符串的监视器时,它将阻止另一个线程获取同一个监视器。 重要的是要理解synchronized块正在获取与字段相关联的监视器的锁定 – 涉及两个单独的字段并不重要。

道德:不要在字符串上同步,特别是文字。 文字特别糟糕,因为在这种情况下,您可以使用与A相同的代码创建另一个类,并且还可以尝试使用同一个监视器进行同步。

以这种方式锁定弦乐可能是危险的。 根据Java语言规范的第3.10.5节 :

不同包中不同类中的文字字符串同样表示对同一String对象的引用。

这意味着如果另一个类包含相同的字符串文字,它将引用相同的String对象并可能导致死锁。

最好使用java.util.concurrent.locks包中的一个显式锁,甚至是new Object()

例:

 private final ReentrantLock lock = new ReentrantLock(); String str = "hello"; public void run(){ lock.lock(); try{ System.out.println(str+" "+Thread.currentThread().getName()); Thread.sleep(100); System.out.println(str+" "+Thread.currentThread().getName()); } finally{ lock.unlock(); } }