Java~使用synchronized修饰静态方法带来的问题 与 同步synchronized代码块不使用String作为锁对象的原因
程序员文章站
2022-06-09 20:11:22
文章目录使用synchronized修饰静态方法带来的问题同步synchronized代码块不使用String作为锁对象的原因使用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...
使用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_Static 1601380417431进入printC 1601380417531离开printA_Static 1601380417531离开printC 1601380417531进入printC 1601380417531进入printA_Static 1601380417631离开printC 1601380417631进入printC 1601380417632离开printA_Static 1601380417632进入printA_Static 1601380417732离开printC 1601380417732进入printC 1601380417733离开printA_Static 1601380417733进入printB_Static 1601380417832离开printC 1601380417832进入printC 1601380417833离开printB_Static 1601380417833进入printB_Static 1601380417932离开printC 1601380417932进入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(); } }
- 运行结果
A
A
A
A
A
A
Process 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对象却是同一个, 也就是上的其实是同一把锁.
本文地址:https://blog.csdn.net/Shangxingya/article/details/108874746
上一篇: 初一吃饺子的寓意