并发变成多线程基础(草稿2)

java内置模型

第一节
  • 内置锁:指的就是synchronized的锁
  • 显示锁:指的就是lock对象的锁
第二节
  • 线程安全问题:当多个线程共享同一个全局变量,当我们做写的操作的时候,可能会受到其他线程的干扰,读操作是不会发生线程安全问题的。不能保证线程的可见性,即一个线程修改了变量,另一个线程可能取到的值是该线程修改之前的值。会造成脏读。

  • 解决线程安全问题:

  1. 内置锁(synchronized):能够保证线程的原子性和可见性,当线程进入方法的时候自动获取锁,一旦锁被获取,其他线程就会等待,只有释放之后才会竞争锁。他会降低程序的运行效率,因为在进入加锁的方法之前都会竞争,其他线程没有竞争上的就会等待。
    synchronized是一个可重入锁。
    内置锁,也是互斥锁,即一个线程拿到后,其他线程无法得到。
    使用方式:
    (1)同步方法,锁的是this对象。
    (2)同步代码块,锁的是指定的对象。
  2. 显示锁(lock)
第三节
  • 不要把synchronized锁加到run方法上,这样会让程序变为单线程。
  • 分类:
    (1)同步代码块,锁的是指定的全局对象(成员变量,this等)
    (2)非静态同步方法,锁this对象
    (3)静态同步方法,锁类对象,字节码文件。
    在这里插入图片描述
    注意:
    synchronized加到静态方法中,相当于是锁的是类的二进制字节码即XXX.class,只能锁字节码文件,即使锁的是一个静态变量,也不生效。
第六节
  • 死锁:同步中嵌套同步。A有锁(一个锁对象,比如this),B也有锁(锁另一个对象),A方法中调用B,B方法中调用A,一个线程进入A,一个线程进入B,两个线程都请求彼此,都不释放。可以参考下图理解。(方法A,B是两个不同的锁,锁不同的对象)
  • 在这里插入图片描述
  • t1 t2是两个线程
    注意:同步中不要嵌套同步
第七节
  • Threadlocal
  • Threadlocal是为了给每个线程提供自己的局部变量,每个线程独享,不共享。
public static ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>(){
	protected Integer initValue(){
		return 0;
	}
};

threadLocal.set(XXX);
threadLocal.get(XXX);
  • ThreadLocal的底层是一个Map集合
  • 在这里插入图片描述
  • ThreadLocal会发生内存泄漏的问题
第八节
  • 多线程的特性:原子性,可见性,有序性
    (1)原子性保证的是线程安全问题
    (2)可见性保证的是变量修改,其他线程可见,拿到的共享变量是最新的
    (3)有序性,保证的是重排序后的有序,不改变运行结果

  • JAVA内存模型
    (1)内存模型并不是堆栈的概念
    (2)内存模型其实是JMM,多线程相关的(原子性,可见性等。);而内存结构,是JVM相关,堆栈方法区等。
    (3)JAVA内存模型简称为JMM,JMM是决定一个线程对共享变量的写入的时候是否对另一个线程可见。他是一个抽象的概念。
    (4)主内存,本地内存
    主内存:表示共享存储的变量
    本地内存:共享变量的副本
    所有的变量都是在主内存中存储,然后复制一个副本到其本地内存中。
    在这里插入图片描述
    举例说:
    我们定义了一个成员变量count,就会先放到共享变量的主内存中。
    复制主内存变量到其t1和t2线程的本地内存中。两个线程的本地内存互不影响。
    这时候,t1和t2同时操作共享变量count,都做++操作。
    此时其各自的本地内存的count都是0,t1的count++后变为1,t2的count++后也变为1,此时各自的本地内存中的count都是1。
    此时本地内存刷新到主内存中,会发现即使加了两次,其主内存的count值也都是1。(注意,最开始修改的时候都是在各自的本地内存中进行修改,并且各自线程的本地内存互不影响,不可见)
    这就是我们线程安全问题。

  • synchronized保证了同时只有一个线程执行,即同时只有一个线程操作count++,此时线程1的count值自增操作结束后,刷新到主内存中,此时再把主内存的值拷贝一个副本到t2线程中。此时t2的count就是修改后的count,再做++操作的时候,就是正常的。

第九节
  • 建议以后使用共享变量的时候都加上volatile关键字
  • volatile保证了可见性,但不保证原子性,所以建议我们可以一起使用volatile和synchronized关键字
  • volatile是保证我们本地内存中每一次修改都立即去刷新下主内存中的值。(这就是可见性)
  • volatile对另一个线程可见,将用户内存修改的变量立即刷新到主内存中,但是volatile只保证了可见性,不能保证了原子性,所以不能保证其线程安全。
  • volatile的性能是高于synchronized的
  • 一般只要是全局共享的变量,全部都加上volatile关键字。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值