javaEE多线程(二)---线程安全以及锁(Lock)

本文探讨了线程安全的定义及其出现的原因,包括原子性破坏、内存可见性和代码重排序,重点介绍了锁的概念与应用,如synchronized和Java并发工具。还涉及了常见类的线程安全问题以及死锁现象。通过实例解析和对比,帮助开发者理解和应对线程安全挑战。
摘要由CSDN通过智能技术生成

目录

1.什么是线程安全?

2线程安全出现的原因。

2.1系统角度分析线程不安全的原因------原子性被破坏

2.2系统角度分析线程不安全的原因------内存可见性问题(memory visiable)

2.3 系统角度分析线程不安全的原因------代码重排序导致的问题

2.4JVM中的代码重排序的基本原则

3.常见类的线程安全问题

4.保护线程安全的措施------锁(Lock)

5.关于锁的应用 

6.锁的介绍

7.synchronized锁与juc下锁的比较

8.死锁

9. 更加细化的线程状态

1.什么是线程安全?

就是运行结果100%符合预期。

线程不安全就无法得到100%预期的结果

2线程安全出现的原因。

1.站在开发者的角度

a:多个线程之间操作了同一块数据(共享数据),不仅仅是内存数据

b.至少有一个线程在修改这块共享数据,也就是多个线程中至少有一个对共享数据做修改的线程。

而在多线程中不需要考虑线程安全问题:

a.几个线程之间互相没有任何数据共享的情况下,天生是线程安全的。

b.几个线程之间即使有共享数据,但都是做读数据,没有写操作,也是天生线程安全的。

2.系统角度解释

a.破环了原子性(最常见的原因)

b.内存可见性问题

一些线程对数据的操作,很可能其他线程无法感知,甚至某些情况下,会被优化成完全看不到的结果(也就是程序读到了脏数据)

c.代码重排序导致的问题

我们写的程序经过中间很多环节的结果,并不保证最终执行的语句和我们最初的语句一模一样

2.1系统角度分析线程不安全的原因------原子性被破坏

代码展示:

问题:

2.2系统角度分析线程不安全的原因------内存可见性问题(memory visiable)

学习委员拿到了脏数据

2.3 系统角度分析线程不安全的原因------代码重排序导致的问题

2.4JVM中的代码重排序的基本原则

3.常见类的线程安全问题

ArrayList、LinkedList、PriorityQueue、TreeMap、TreeSet、HashMap、HashSet、StringBuilder都不是线程安全

线程安全的类有Vector、Stack、Dictionary、StringBuffer。

这几个类都是Java设计的失败品,以后代码尽量不要用。

StringBuilder与StringBuffer的区别是:一个线程安全一个线程不安全

4.保护线程安全的措施------锁(Lock)

所谓的锁:就是一段数据(一段被多个线程之间共享的数据)

释放锁的操作(纯理论):

这个系统由系统保证了原子性。

当多个线程都有加锁操作时,并且申请的是同一把锁时:

synchronize 锁、同步锁、monitor锁(监视器锁)

语法:

1.修饰方法(普通方法、静态方法)=》同步方法

synchronize int add(...){...}

2.同步代码块

synchornize (引用){...}

5.关于锁的应用 

6.锁的介绍

synchronized是一种非常早期存在的锁,后期重新设计过,以类、对象的形式给我们使用。

现在我们java并发编程尽量用这个包下面的提供的工具,java.util.cincurrent.*(JUC包)

java.util.concurrent.locks.Lock  (相比于sync锁,加锁策略更灵活)

lock();   //等同于sync锁

lockInterruptibly();  //加锁,允许被中断

tryLock();  //加锁失败后返回false

tryLock(long time,TimeUnit unit); //加锁失败后返回false,尝试等待一段时间,这段时间过去之后,加锁失败。

unlock(); //解锁操作

7.synchronized锁与juc下锁的比较

1.保证了临界区的原子性(可以加锁使得原子性的代码之间互斥来实现)(90%,最重要)

加锁的粒度可以不同。

2.可以保证内存的可见性(在有限程度上)(5%)

3.可以给代码重排序增加一定的约束(5%)

8.死锁

即主线程在调用t.join()在等待结束,子线程在调用lock.lock()等待主线程(所持有的线程)释放锁。

这里的死锁和操作系统不同,操作系统是死锁与资源分配有关

9. 更加细化的线程状态

我们可以看出,当线程处于waiting状态的时候。说明线程正在等待锁,或者等待子线程执行结束。

blocked专指请求sync锁失败的状态。

更加细致的状态转移图:

 

问:操作系统的死锁是什么?

还有个问题?

 t.join()等待的是子线程吗?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值