常见锁介绍
synchronized锁的八中情况
- package com.shaonian.juc.more_thread_lock;
- import java.util.concurrent.TimeUnit;
- class Phone {
- public static synchronized void sendSMS() throws Exception {
- //停留4秒
- TimeUnit.SECONDS.sleep(4);
- System.out.println("------sendSMS");
- }
- public synchronized void sendEmail() throws Exception {
- System.out.println("------sendEmail");
- }
- public void getHello() {
- System.out.println("------getHello");
- }
- }
- /**
- * @Description: 8锁
- *
- 1 标准访问,先打印短信还是邮件
- ------sendSMS
- ------sendEmail
- 2 停4秒在短信方法内,先打印短信还是邮件
- ------sendSMS
- ------sendEmail
- 3 新增普通的hello方法,是先打短信还是hello
- ------getHello
- ------sendSMS
- 4 现在有两部手机,先打印短信还是邮件
- ------sendEmail
- ------sendSMS
- 5 两个静态同步方法,1部手机,先打印短信还是邮件
- ------sendSMS
- ------sendEmail
- 6 两个静态同步方法,2部手机,先打印短信还是邮件
- ------sendSMS
- ------sendEmail
- 7 1个静态同步方法,1个普通同步方法,1部手机,先打印短信还是邮件
- ------sendEmail
- ------sendSMS
- 8 1个静态同步方法,1个普通同步方法,2部手机,先打印短信还是邮件
- ------sendEmail
- ------sendSMS
- */
- public class Lock8QuestionBySynchronized {
- public static void main(String[] args) throws Exception {
- Phone phone = new Phone();
- Phone phone2 = new Phone();
- new Thread(() -> {
- try {
- phone.sendSMS();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }, "AA").start();
- Thread.sleep(100);
- new Thread(() -> {
- try {
- // phone.sendEmail();
- // phone.getHello();
- phone2.sendEmail();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }, "BB").start();
- }
- }
复制代码 代码结果原因分析,见博客中synchronized关键字回顾。
ReentrantLock读写锁分析
- /**
- * Creates an instance of {@code ReentrantLock}.
- * This is equivalent to using {@code ReentrantLock(false)}.
- */
- public ReentrantLock() {
- sync = new NonfairSync();//默认是非公平锁
- }
- /**
- * Creates an instance of {@code ReentrantLock} with the
- * given fairness policy.
- *
- * @param fair {@code true} if this lock should use a fair ordering policy
- */
- public ReentrantLock(boolean fair) {//传入false,定义的就是非公平的读写锁
- sync = fair ? new FairSync() : new NonfairSync();
- }
复制代码 非公平锁(ReentrantLock实现)
非公平锁是多个线程加锁时直接尝试获取锁,能抢到锁到直接占有锁,抢不到才会到等待队列的队尾等待。确定可能会出现线程饿死现象(锁一直被一个线程持有,某些线程一直拿不到锁),优点是执行效率高,可以直接获取锁。- static final class NonfairSync extends Sync {//ReentrantLock中的静态内部类
- private static final long serialVersionUID = 7316153563782823691L;
- /**
- * Performs lock. Try immediate barge, backing up to normal
- * acquire on failure.
- */
- final void lock() {
- if (compareAndSetState(0, 1))
- setExclusiveOwnerThread(Thread.currentThread());
- else
- acquire(1);
- }
- protected final boolean tryAcquire(int acquires) {
- return nonfairTryAcquire(acquires);
- }
- }
复制代码 公平锁(ReentrantLock实现)
公平锁是指多个线程按照申请锁的顺序来获取锁,线程直接进入队列中排队,队列中的第一个线程才能获得锁。保证每个线程都能拿到锁,优点是执行效率比非公平锁低,优点是不会出现线程饿死现象。- static final class FairSync extends Sync {
- private static final long serialVersionUID = -3000897897090466540L;
- final void lock() {
- acquire(1);
- }
- /**
- * Fair version of tryAcquire. Don't grant access unless
- * recursive call or no waiters or is first.
- */
- protected final boolean tryAcquire(int acquires) {
- final Thread current = Thread.currentThread();
- int c = getState();
- if (c == 0) {
- if (!hasQueuedPredecessors() &&
- compareAndSetState(0, acquires)) {
- setExclusiveOwnerThread(current);
- return true;
- }
- }
- else if (current == getExclusiveOwnerThread()) {
- int nextc = c + acquires;
- if (nextc < 0)
- throw new Error("Maximum lock count exceeded");
- setState(nextc);
- return true;
- }
- return false;
- }
- }
复制代码 可重入锁(ReentrantLock实现)
synchronized(隐式)和Lock(显式)都是可重入锁,也叫递归锁。特点,类似于,有了第一把锁,此锁内部锁的代码都可以访问。像开了大门,开剩下的门就不用再用钥匙开门了。- /**
- * @author 长名06
- * @version 1.0
- * 可重入锁案例
- */
- public class ReentrantLockDemo {
- private synchronized void add(){
- add();
- }
- public static void main(String[] args) {
- //new ReentrantLockDemo().add();//会出现StackOverflowError
- Object o = new Object();
- new Thread(() -> {
- synchronized (o){
- System.out.println(Thread.currentThread().getName() + "外部");
- synchronized (o){
- System.out.println(Thread.currentThread().getName() + "中部");
- synchronized (o){
- System.out.println(Thread.currentThread().getName() + "内部");
- }
- }
- }
- },"aa").start();
-
- ReentrantLock lock = new ReentrantLock();
- new Thread(() -> {
- try{
- lock.lock();
- System.out.println(Thread.currentThread().getName() + "外层操作");
- try{
- lock.lock();
- System.out.println(Thread.currentThread().getName() + "内层操作");
- }finally {
- lock.unlock();
- }
- }finally {
- lock.unlock();
- }
- }).start();
- //结果
- //Thread-0外层操作
- //Thread-0内层操作
- }
- }
复制代码 死锁
基本介绍
死锁,是一种多个线程在执行过程中,因竞争资源时,导致线程互相持有其他线程执行需要的锁,从而引起线程等待的现象。在没有外力的作用下,程序会崩溃。
引起死锁的原因
- 1.系统资源不足。
- 2.进程运行顺序不合适。
- 3.资源分配不当。
- /**
- * @author 长名06
- * @version 1.0
- * 死锁代码
- */
- public class DeadLock {
- static Object a = new Object();
- static Object b = new Object();
- public static void main(String[] args) {
- new Thread(() -> {
- synchronized (a){
- System.out.println(Thread.currentThread().getName() + "持有锁a,试图后去锁b");
- try {
- TimeUnit.SECONDS.sleep(1);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- synchronized (b){
- System.out.println(Thread.currentThread().getName() + "获取锁b");
- }
- }
- },"a").start();
- new Thread(() -> {
- synchronized (b){
- System.out.println(Thread.currentThread().getName() + "持有锁b,试图后去锁a");
- try {
- TimeUnit.SECONDS.sleep(1);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- synchronized (a){
- System.out.println(Thread.currentThread().getName() + "获取锁a");
- }
- }
- },"b").start();
- }
- }
复制代码 验证线程一直等待是否是死锁
- 1.jps -l 命令类似linux下的ps - ef 可以查询java的线程

正在执行的死锁代码的进程id
- 2.jstack工具(JVM 自带的堆栈工具) jstack 线程id 可以查询对应线程的信息
执行jstack pid指令
提示语句中会有 Found 1 deadlock
只是为了记录自己的学习历程,且本人水平有限,不对之处,请指正。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |