java学习(十一)-线程和java的锁

一、线程与进程
1.1、定义
  • 进程:系统进行资源分配和调度的一个独立单位.
  • 线程:进程的一个实体,是CPU调度和分派的基本单位,线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.
  • 一个进程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行.
1.2、区别
  • 一个程序至少有一个进程,一个进程至少有一个线程。多个端口相当于多个进程
  • 进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率
  • 进程的切换使用的是进程上下文,涉及到内核对用户态到核心态的切换,再从核心态到另一个用户态的切换,涉及系统层面,这种切换非常耗性能;线程的切换是线程上下文,相对进程而且,较简单
1.21、从以下几个方面考虑
  • 1.地址空间和其他资源(如打开文件):进程间相互独立,同一进程的各线程间共享。某进程内的线程在其他进程内不可见。

  • 2.通信:进程间通信IPC(管道,信号量,共享内存,消息队列),线程间可以直接独写进程数据段(如全局变量)来进程通信——需要进程同步和互斥手段的辅助,以保证数据的一致性。

  • 3.调度和切换:线程上下文切换比进程上下文切换快得多。

  • 4.在多线程OS中,进程不是一个可执行的实体。

1.3、线程的创建和执行
  • Thread是线程类,用户自己创建线程的实例。先创建线程任务,将线程任务当做参数传递给线程的构造函数。往往线程任务代表该线程要做的内容
  • java虚拟机会负责主线程的启动,程序负责启动自己创建的线程(start()函数)
  • 线程有三种状态:1、执行中状态;2、可执行状态;3、暂时不可执行状态(阻塞状态)
  • java虚拟机的调度器决定着多个线程执行顺序的切换。单处理器的机器只能有一个正在执行的线程
1.4、同步化
  • 每个java对象都有一把锁,每个锁只有一把钥匙。
  • 对象若有同步化的方法,则线程只有在取得钥匙的情况下才能进入该线程(也就是没有其他线程进入的情况下才能进入)
  • 同步化其实是为了保护重要的数据,实际上,其锁住的不是数据,而是存储数据的方法。
  • 同步化的方法,用synchronize标识(如:public synchronize void increment() {})
1.5、同步化的缺点
  • 查询是否有钥匙可用的性能问题
  • 强制的线程排队(使并行线程操作的高效优势打折扣)
  • 死锁现象
1.6、死锁
  • 死锁代表两个现场互相持有对方正在等待的东西。
  • 数据库也可能存在死锁,但是有实物回滚机制来复原不能全部完成的任务
二、锁的类型

乐观锁/悲观锁
独享锁/共享锁
互斥锁/读写锁
可重入锁
公平锁/非公平锁
分段锁
偏向锁/轻量级锁/重量级锁
自旋锁
以上是一些锁的名词,这些分类并不是全是指锁的状态,有的指锁的特性,有的指锁的设计

2.1、独享锁/共享锁(广义的概念)
  • 独享锁:是指该锁一次只能被一个线程所持有。
  • 共享锁:指的是多个线程可以同时拥有一把锁。这些共享锁的线程会从等待队列中出来,进入执行状态,当全部执行完成,会唤起队列中等待的下一个线程节点。
  • 一些案例:
    • Java ReentrantLock而言,其是独享锁
    • Lock的另一个实现类ReadWriteLock,其读锁是共享锁,其写锁是独享锁。(读锁的共享锁可保证并发读是非常高效的,读写,写读,写写的过程是互斥的)
    • Synchronized而言,当然是独享锁。
2.2、互斥锁与读写锁(实现类ReentrantReadWriteLock)(具体的实现)
  • 互斥锁:指的是多个线程中,只能有一个线程获取该锁。其他未获得锁的线程中,在队列中排队等候,等待正在执行的线程结束后,唤起队列中下一个线程节点,若下一个线程的操作是读操作,则唤起的是所有等待读操作锁的线程节点。
  • 读锁:一般来说,读锁都是共享锁。多个线程可以同时拥有读锁,进行读操作;
  • 写锁:写锁都是独享锁,一次只能有一个线程拥有写锁。所有的写锁,会阻塞读锁操作。
2.3、非公平锁与公平锁
  • 非公平锁:指当锁状态为可用时,不管在当前锁上是否有其他线程在等待,新近线程都有机会抢占锁。
  • 公平锁:当多个线程尝试获取锁时,成功获取锁的顺序与请求获取锁的顺序相同
  • 非公平锁的优点在于吞吐量比公平锁大。
2.4、乐观锁与悲观锁
  • 悲观锁:认为同一数据的操作,一定会发生修改,一定需要加上锁,认为不加锁一定会出现问题
  • 乐观锁:认为同一数据的操作,一定不会发生修改,认为不加锁的并发操作是没有问题的。在更新的时候,采取尝试更新。
  • 乐观锁的两种实现方式有:版本号控制和CAS自旋锁方式
  • 版本号控制是指:查询锁会读取该版本号,当进行写操作的时候,会拿着之前读的版本号和现在存在的版本号进行比较,若一致,则认为这段期间内没有线程修改该数据,我的更新操作是合理的,则执行更新操作并更新版本号;若不一致,则这个更新操作会失败,重新获取该锁和数据状态,重新进行更新操作
  • CAS自旋等着锁可用,一定程度上可以避免很多线程切换的上下文操作,但是等待一定时间之后还是会被阻塞取消等待。这种适合于读多写少的操作,因为自旋等待少部分的时候,就可以获取到锁执行操作
2.5、可重入锁
  • 可重入锁,也称递归锁;当外层方法获取了该锁,进入内部递归方法(即该方法本身)可自动获取到该锁
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值