并发编程(JAVA版)-------------(三)

本文承接一并发编程(JAVA版)-------------(一)

本文承接二并发编程(JAVA版)-------------(二)

共享模型之管程

面对共享资源的重要知识:原子性,对象的选择

  • synchronized实际是用对象锁保证了临界区内代码的原子性,临界区内的代码对外是不可分割的,不会被线程切换所打断。
    关于线程的理解,可以上网搜一下线程八锁问题,这个是我在学习的过程中觉得非常不错的关于线程理解的问题,看一下总归是有好处的,你们随意,要是觉得好的话,记得回来点个赞,支持一下博主,你们的支持是我最大的动力。

变量的线程安全分析

成员变量和静态变量是否线程安全?

  • 如果它们没有共享,则线程安全
  • 如果它们被共享了,根据它们的状态是否能够改变又分两种状态:
    • 如果只有读操作,则线程安全
    • 如果有读写操作,则这段代码是临界区,需要考虑线程安全

局部变量是否线程安全?

  • 局部变量是线程安全的
  • 但局部变量引用的对象则未必
    • 如果该对象没有逃离方法的作用访问,它是线程安全的
    • 如果该对象逃离方法的作用范围,则需要考虑线程安全(可用final、private来加强安全性)

常见的线程安全类

  • String
  • Integer
  • StringBuffer
  • Random
  • Vector
  • Hashtable
  • jave.util.concurrent包下的类(简称JUC)
    这里说它们是线程安全的是指,多个线程调用它们同一个实例的某个方法时,线程是安全的。也可以理解为:
Hashtable table = new Hashtable();
new Thread(()->{
	table.put("key","value1");
}).start();
new Thread(()->{
	table.put("key","value2");
}).start();
  • 它们的每一个方法是原子的
  • 注意它们多个方法的组合不是原子的,见后面的分析

不可变类线程安全性

String、Integer等都是不可变类,因为其内部的状态不可以改变,因此它们的方法都是线程安全的。
说到这里,肯定就有同学有疑问,String有replace、substring等方法【可以】改变值啊,那么这些方法又是如何保证线程安全的呢?
答案是通过阅读源码可以了解,在这些方法里通过新建对象来保证线程安全。

Monitor(锁)工作原理

Monitor被翻译为监视器管程
每个Java对象都可以关联一个Monitor对象,如果使用synchronized给对象上锁(重量级)之后,该对象头的Mark Word中就被设置指向Monitor对象的指针

  • 刚开始Monitor中Owner为null
  • 当Thread2执行synchronized(obj)就会将Monitor的所有者Owner置为Thread2,Monitor中只能有一个Owner
  • 在Thread2上锁的过程中,如果Thread3,Thread4,Thread5也来执行synchronized(obj),就会进入EntryList BLOCKED
  • Thread2执行完同步代码块的内容,然后唤醒EntryList中等待的线程来竞争锁,竞争的时候是非公平的,是由JDK底层实现决定的

注意

  • synchronized必须是进入同一个对象的monitor才有上述效果
  • 不加synchronized的对象不会关联监视器,不遵循以上规则
发布了19 篇原创文章 · 获赞 6 · 访问量 400

猜你喜欢

转载自blog.csdn.net/weixin_44350891/article/details/104659022