程序员最近都爱上了这个网站  程序员们快来瞅瞅吧!  it98k网:it98k.com

本站消息

站长简介/公众号

  出租广告位,需要合作请联系站长


+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

多线程基础---线程安全(原因及解决方法),synchronized,volatile关键字

发布于2021-06-12 15:00     阅读(126)     评论(0)     点赞(10)     收藏(4)


目录

1. 中断线程

2. 线程等待

3. 守护线程

4. Java中的线程状态

5. 线程安全

1) 背景/原因

2) 线程安全的解决

6.  synchronized 同步关键字

7.  volatile


1. 中断线程

1) 使用标志位的方式

isStop变量.

  1. public class FlagStop {
  2. private static volatile boolean isStop;
  3. public static void main(String[] args) throws InterruptedException {
  4. new Thread(new Runnable() {
  5. @Override
  6. public void run() {
  7. try {
  8. while (!isStop) {
  9. System.out.println("转账....");
  10. Thread.sleep(1000);
  11. }
  12. }catch (InterruptedException e){
  13. e.printStackTrace();
  14. }
  15. }
  16. }).start();
  17. //停止转账
  18. Thread.sleep(3000);
  19. isStop=true;
  20. }
  21. }

2) 线程中断的API

前置: 线程Thread中,存在一个中断标志位,默认值=false(没有被中断)

   

     

      

  1. public class InterruptThread {
  2. public static void main(String[] args) throws InterruptedException {
  3. Thread t=new Thread(new Runnable() {
  4. @Override
  5. public void run() {
  6. try {
  7. while(!Thread.currentThread().isInterrupted()){
  8. System.out.println("转账...");
  9. Thread.sleep(1000);
  10. }
  11. } catch (InterruptedException e) {
  12. e.printStackTrace();
  13. }
  14. }
  15. });
  16. t.start();
  17. Thread.sleep(3000);
  18. t.interrupt();
  19. }
  20. }

2. 线程等待

1)  API

线程引用对象.join()     /    线程引用对象.join(long)

当前线程阻塞等待,直到满足以下条件:

无参: 线程引用执行完毕

有参: 等待指定时间,或者线程引用执行完毕,任意一个条件满足,当前线程继续向下执行.

2) 示例

  1. public class LearnJoin {
  2. public static void main(String[] args) throws InterruptedException {
  3. Thread t=new Thread(new Runnable() {
  4. @Override
  5. public void run() {
  6. try{
  7. System.out.println("t start");
  8. Thread.sleep(5000);
  9. System.out.println("t end");
  10. }catch(InterruptedException e){
  11. e.printStackTrace();
  12. }
  13. }
  14. });
  15. t.start();
  16. t.join(2000);
  17. System.out.println("main");
  18. }
  19. }

3. 守护线程

1) API

参数为:

true: 设置为守护线程;

false: 设置为用户线程.

2) 一个Java进程,至少有一个用户线程存在,才会运行,否则就结束.

4. Java中的线程状态

这里的等待,超时等待,阻塞状态,和之前学习的进程状态转换图,阻塞状态,表现是一样的,线程暂停/挂起.

5. 线程安全

1) 背景/原因

代码层面上: 多个线程对同一个共享数据的操作(读,写),如果有写操作,就存在线程安全问题.

底层的原因: 原子性,可见性,有序性.

① 原子性

  • 一系列的操作(多行代码指令的执行),需要具有不可分割的特性,就是原子性.
  • 如果可以被分割,指令之间,可能有其他线程并发并行执行的操作,对同一个共享变量操作就会产生影响.

特殊的非原子性操作:

a) n++,n--,++n,--n

           从主存把数据读取到CPU  (读)

   进行数据的更新  (改)

   把数据写回到主存  (写回)

b) new一个对象

       

        一行new对象的代码,分解为:

        I. 分配内存空间(Java虚拟机)

       II. 执行构造方法(字节码层面的<init>构造方法: 收集成员变量,实例代码块,Java代码中的构造方法)

      III. 把new的对象赋值给变量

② 可见性

线程对主存数据的操作,需要先加载到线程私有的工作内存,操作完再写回到主存,线程之间的工作内存,是互相不可见的.

       

共享变量,存储于主存(线程共享区域),线程对变量的操作:

a) 加载到工作内存

b) 操作(赋值,修改)

c) 写回主存

③ 重排序

多行指令(字节码指令在Java虚拟机执行,及机器码指令在CPU执行)在执行时,可能进行优化(目的是提高执行效率),只是不能重排序有关联的指令.

比如洗苹果,吃苹果,这两条指令由于具有前后关系,所以就不能重排序.洗苹果,洗梨,就可以进行重排序.

2) 线程安全的解决

线程安全,是由于多个线程对共享变量的操作,并发并行执行的结果.(共享变量称为临界资源,这种代码(多行),称为临界区)

思路: 临界区代码执行时,先申请jvm加锁,然后再执行. 申请锁,是需要同一把锁来保证线程安全;申请失败,线程则需要等待(可以是阻塞式的,也可以是非阻塞式)

这种操作,在多个线程执行临界区都申请同一把锁的情况下,多个线程运行的结果,就表现为: 多个线程,依次执行临界区代码.

假如现在我(线程)----申请把餐厅101包间加锁---吃饭,喝水(临界区: 此时作为不可分割的最小执行单位)----归还锁---通知其他要在101做事的人(其他线程)---重复以上流程.

6.  synchronized 同步关键字

1) 作用:

基于对象头加锁的方式,只要申请同一把锁加锁的线程,都有同步互斥的作用.

  • 对象: 某个对象加锁(本质是对象在内存中的对象头加锁)
  • 同一把锁: 是否为同一个对象加锁.
  • 同步互斥: 多个线程之间执行synchronized作用域范围的临界区代码,是一个一个依次执行.

2) 语法:

  • ①静态同步方法: 使用的锁为当前的类对象
  • ②实例同步方法: 使用的锁为当前调用的实例对象(this)
  • ③同步代码块: 使用的锁,为小括号中的对象

语法上对应申请锁-----加锁----释放锁

synchronized代码行: 线程申请某个对象锁

synchronized作用域结束(花括号结束): 自动释放对象锁.

3) 特别注意的事项:

多线程只有申请同一个对象的加锁,才具有同步互斥的效果.

不是对同一个对象加锁,并发并行的执行.(部分A加同一把锁,部分B不加锁,A中的多个线程同步互斥,但是B和A,B内部的多个线程,都是并发并行)

7.  volatile

1) 作用

①保证变量(分解为字节码以后的)的可见性.

②建立一个内存屏障,禁止指令重排序.

2) 使用场景:

代码行本身保证原子性的前提下,变量使用volatile修饰,可以保证线程安全.

关于代码行本身保证原子性的理解:

①读(从主存读取到线程的工作内存)

②修改为一个常量值(把常量值写回主存)

 

 

原文链接:https://blog.csdn.net/weixin_43939602/article/details/117441171



所属网站分类: 技术文章 > 博客

作者:狗蛋来了

链接:http://www.javaheidong.com/blog/article/222576/7e8931a996477802c724/

来源:java黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

10 0
收藏该文
已收藏

评论内容:(最多支持255个字符)