![Java多线程编程核心技术(第3版)](https://wfqqreader-1252317822.image.myqcloud.com/cover/745/42637745/b_42637745.jpg)
上QQ阅读APP看书,第一时间看更新
2.2.17 String常量池特性与同步问题
JVM具有String常量池的功能,所以如图2-48所示的结果为true。
![](https://epubservercos.yuewen.com/204B22/22139293909121606/epubprivate/OEBPS/Images/2-48.jpg?sign=1738884524-GD6OfdrN2lyRKPjHYblpeE0zq1WDwfzq-0-f5785a0bb2745a0774c9f9808238bb92)
图2-48 String常量池缓存
在将synchronized(string)同步块与String联合使用时,要注意常量池会带来一些意外。
新建名称为StringAndSyn的项目,类文件Service.java代码如下:
package service; public class Service { public static void print(String stringParam) { try { synchronized (stringParam) { while (true) { System.out.println(Thread.currentThread().getName()); Thread.sleep(1000); } } } catch (InterruptedException e) { e.printStackTrace(); } } }
两个自定义线程代码如图2-49所示。
运行类Run.java代码如下:
package test; import service.Service; import extthread.ThreadA; import extthread.ThreadB; public class Run { public static void main(String[] args) { Service service = new Service(); ThreadA a = new ThreadA(service); a.setName("A"); a.start(); ThreadB b = new ThreadB(service); b.setName("B"); b.start(); } }
![](https://epubservercos.yuewen.com/204B22/22139293909121606/epubprivate/OEBPS/Images/2-49.jpg?sign=1738884524-UoasuJcTAfxUkp1EgbYS3g2gOSdU6J0V-0-4121e29451ed9e9289acec32d2323f10)
图2-49 线程类代码
程序运行结果如图2-50所示。
![](https://epubservercos.yuewen.com/204B22/22139293909121606/epubprivate/OEBPS/Images/2-50.jpg?sign=1738884524-8FisNPzNKx1gpP8AvcwkUyJjXmzIxKL0-0-26e8e89923674aeb443f412aa14dae9b)
图2-50 死循环
出现这种情况就是因为String的两个值都是”AA”,两个线程是持有相同的锁,造成线程B不能执行。这就是String常量池所带来的问题,所以大多数情况下,同步synchronized代码块都不使用String作为锁对象,而改用其他,例如new Object()实例化一个新的Object对象时,它并不放入缓存池中,或者执行new String()创建不同的字符串对象,形成不同的锁。
继续实验,创建名称为StringAndSyn2的项目,类文件Service.java代码如下:
package service; public class Service { public static void print(Object object) { try { synchronized (object) { while (true) { System.out.println(Thread.currentThread().getName()); Thread.sleep(1000); } } } catch (InterruptedException e) { e.printStackTrace(); } } }
两个自定义线程如图2-51所示。
![](https://epubservercos.yuewen.com/204B22/22139293909121606/epubprivate/OEBPS/Images/2-51.jpg?sign=1738884524-AAU6GYF5sYFaXlf4qPDZksv8KEZcm5He-0-fcb20ccb2ff8841100f7729c5b866655)
图2-51 自定义线程代码
运行类Run.java代码如下:
package test; import service.Service; import extthread.ThreadA; import extthread.ThreadB; public class Run { public static void main(String[] args) { Service service = new Service(); ThreadA a = new ThreadA(service); a.setName("A"); a.start(); ThreadB b = new ThreadB(service); b.setName("B"); b.start(); } }
程序运行结果如图2-52所示。
![](https://epubservercos.yuewen.com/204B22/22139293909121606/epubprivate/OEBPS/Images/2-52.jpg?sign=1738884524-tZ2HdHaMPAGbz8f3iuCgqPRwZJrlsy1h-0-199e9e9d526992db848cdfdd8a45a3d5)
图2-52 交替输出
交替输出的原因是持有的锁不是一个。