博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java~使用synchronized修饰静态方法带来的问题 与 同步synchronized代码块不使用String作为锁对象的原因
阅读量:4050 次
发布时间:2019-05-25

本文共 4549 字,大约阅读时间需要 15 分钟。

文章目录

使用synchronized修饰静态方法带来的问题

  • 直接上代码
/** * Created with IntelliJ IDEA. * Description: If you don't work hard, you will a loser. * User: Listen-Y. * Date: 2020-09-29 * Time: 11:39 */public class ServiceStatic {
public synchronized static void printA() {
System.out.println(System.currentTimeMillis() + "进入printA_Static"); try {
Thread.sleep(100); } catch (InterruptedException e) {
e.printStackTrace(); } System.out.println(System.currentTimeMillis() + "离开printA_Static"); } public synchronized static void printB() {
System.out.println(System.currentTimeMillis() + "进入printB_Static"); try {
Thread.sleep(100); } catch (InterruptedException e) {
e.printStackTrace(); } System.out.println(System.currentTimeMillis() + "离开printB_Static"); } public void printC() {
System.out.println(System.currentTimeMillis() + "进入printC"); try {
Thread.sleep(100); } catch (InterruptedException e) {
e.printStackTrace(); } System.out.println(System.currentTimeMillis() + "离开printC"); }}
import javax.net.ssl.SSLContext;/** * Created with IntelliJ IDEA. * Description: If you don't work hard, you will a loser. * User: Listen-Y. * Date: 2020-09-29 * Time: 11:41 */public class Run5 {
public static void main(String[] args) {
Thread thread = new Thread("A") {
@Override public void run() {
while (true) {
ServiceStatic.printA(); } } }; Thread thread1 = new Thread("B") {
@Override public void run() {
while (true) {
ServiceStatic.printB(); } } }; ServiceStatic serviceStatic = new ServiceStatic(); Thread thread2 = new Thread("C") {
@Override public void run() {
while (true) {
serviceStatic.printC(); } } }; thread.start(); thread1.start(); thread2.start(); }}
  • 运行结果
1601380417431进入printA_Static1601380417431进入printC1601380417531离开printA_Static1601380417531离开printC1601380417531进入printC1601380417531进入printA_Static1601380417631离开printC1601380417631进入printC1601380417632离开printA_Static1601380417632进入printA_Static1601380417732离开printC1601380417732进入printC1601380417733离开printA_Static1601380417733进入printB_Static1601380417832离开printC1601380417832进入printC1601380417833离开printB_Static1601380417833进入printB_Static1601380417932离开printC1601380417932进入printC
  • 观察我们发现虽然我们给三个方法printA printB printC 都上了锁, 但是运行结果却是printA与printB是同步的, 与printC是异步的
  • 这就是给static方法上锁带来的问题, 其实异步的原因是持有不同的锁, 一个是实例对象锁, 一个是类对象锁, 而且类对象锁可以对所有对象实例起到作用, 而printC是只对调用这个方法的那个实例对象其作用

同步synchronized代码块不使用String作为锁对象的原因

  • 直接上代码
public class Service {
public void printStr(String str) {
//给Str上锁 synchronized (str) {
while (true) {
System.out.println(Thread.currentThread().getName()); try {
Thread.sleep(1000); } catch (InterruptedException e) {
e.printStackTrace(); } } } }}
public class ThreadA extends Thread {
private Service service; public ThreadA(Service service) {
this.service = service; } @Override public void run() {
service.printStr("Listen"); }}class ThreadB extends Thread {
private Service service; public ThreadB(Service service) {
this.service = service; } @Override public void run() {
service.printStr("Listen"); }}
public class Run4 {
public static void main(String[] args) {
Service service = new Service(); //创建俩个线程去执行 ThreadA threadA = new ThreadA(service); threadA.setName("A"); ThreadB threadB = new ThreadB(service); threadB.setName("B"); threadA.start(); threadB.start(); }}
  • 运行结果
AAAAAAProcess finished with exit code -1
  • 分析结果我们发现, A和B俩个线程都启动了, 但是B线程一直没有得到执行, 也就是B线程一直没有获得锁
  • 这就是使用String作为锁对象带来的问题, 原因就是JVM中有String常量池缓存的功能, 看下面代码示例
public class Test {
public static void main(String[] args) {
String s = "Listen"; String s1 = "Listen"; System.out.println(s==s1); }}
true
  • 由此我们得出, 虽然线程A和线程B传入的不是同一个引用的字符串, 但是这个String对象却是同一个, 也就是上的其实是同一把锁.

转载地址:http://sjsci.baihongyu.com/

你可能感兴趣的文章
nginx+tomcat+memcached (msm)实现 session同步复制
查看>>
c++模板与泛型编程
查看>>
WAV文件解析
查看>>
WPF中PATH使用AI导出SVG的方法
查看>>
WPF UI&控件免费开源库
查看>>
QT打开项目提示no valid settings file could be found
查看>>
Win10+VS+ESP32环境搭建
查看>>
android 代码实现圆角
查看>>
flutter-解析json
查看>>
android中shader的使用
查看>>
java LinkedList与ArrayList迭代器遍历和for遍历对比
查看>>
drat中构造方法
查看>>
JavaScript的一些基础-数据类型
查看>>
转载一个webview开车指南以及实际项目中的使用
查看>>
android中对于非属性动画的整理
查看>>
一个简单的TabLayout的使用
查看>>
ReactNative使用Redux例子
查看>>
Promise的基本使用
查看>>
coursesa课程 Python 3 programming 统计文件有多少单词
查看>>
coursesa课程 Python 3 programming 输出每一行句子的第三个单词
查看>>