多线程锁

打印 上一主题 下一主题

主题 914|帖子 914|积分 2742

常见锁介绍

synchronized锁的八中情况
  1. package com.shaonian.juc.more_thread_lock;
  2. import java.util.concurrent.TimeUnit;
  3. class Phone {
  4.     public static synchronized void sendSMS() throws Exception {
  5.         //停留4秒
  6.         TimeUnit.SECONDS.sleep(4);
  7.         System.out.println("------sendSMS");
  8.     }
  9.     public synchronized void sendEmail() throws Exception {
  10.         System.out.println("------sendEmail");
  11.     }
  12.     public void getHello() {
  13.         System.out.println("------getHello");
  14.     }
  15. }
  16. /**
  17. * @Description: 8锁
  18. *
  19. 1 标准访问,先打印短信还是邮件
  20. ------sendSMS
  21. ------sendEmail
  22. 2 停4秒在短信方法内,先打印短信还是邮件
  23. ------sendSMS
  24. ------sendEmail
  25. 3 新增普通的hello方法,是先打短信还是hello
  26. ------getHello
  27. ------sendSMS
  28. 4 现在有两部手机,先打印短信还是邮件
  29. ------sendEmail
  30. ------sendSMS
  31. 5 两个静态同步方法,1部手机,先打印短信还是邮件
  32. ------sendSMS
  33. ------sendEmail
  34. 6 两个静态同步方法,2部手机,先打印短信还是邮件
  35. ------sendSMS
  36. ------sendEmail
  37. 7 1个静态同步方法,1个普通同步方法,1部手机,先打印短信还是邮件
  38. ------sendEmail
  39. ------sendSMS
  40. 8 1个静态同步方法,1个普通同步方法,2部手机,先打印短信还是邮件
  41. ------sendEmail
  42. ------sendSMS
  43. */
  44. public class Lock8QuestionBySynchronized {
  45.     public static void main(String[] args) throws Exception {
  46.         Phone phone = new Phone();
  47.         Phone phone2 = new Phone();
  48.         new Thread(() -> {
  49.             try {
  50.                 phone.sendSMS();
  51.             } catch (Exception e) {
  52.                 e.printStackTrace();
  53.             }
  54.         }, "AA").start();
  55.         Thread.sleep(100);
  56.         new Thread(() -> {
  57.             try {
  58.                 // phone.sendEmail();
  59.                 // phone.getHello();
  60.                 phone2.sendEmail();
  61.             } catch (Exception e) {
  62.                 e.printStackTrace();
  63.             }
  64.         }, "BB").start();
  65.     }
  66. }
复制代码
代码结果原因分析,见博客中synchronized关键字回顾。
ReentrantLock读写锁分析
  1. /**
  2.      * Creates an instance of {@code ReentrantLock}.
  3.      * This is equivalent to using {@code ReentrantLock(false)}.
  4.      */
  5.     public ReentrantLock() {
  6.         sync = new NonfairSync();//默认是非公平锁
  7.     }
  8.     /**
  9.      * Creates an instance of {@code ReentrantLock} with the
  10.      * given fairness policy.
  11.      *
  12.      * @param fair {@code true} if this lock should use a fair ordering policy
  13.      */
  14.     public ReentrantLock(boolean fair) {//传入false,定义的就是非公平的读写锁
  15.         sync = fair ? new FairSync() : new NonfairSync();
  16.     }
复制代码
非公平锁(ReentrantLock实现)

非公平锁是多个线程加锁时直接尝试获取锁,能抢到锁到直接占有锁,抢不到才会到等待队列的队尾等待。确定可能会出现线程饿死现象(锁一直被一个线程持有,某些线程一直拿不到锁),优点是执行效率高,可以直接获取锁。
  1. static final class NonfairSync extends Sync {//ReentrantLock中的静态内部类
  2.         private static final long serialVersionUID = 7316153563782823691L;
  3. /**
  4. * Performs lock.  Try immediate barge, backing up to normal
  5. * acquire on failure.
  6. */
  7.     final void lock() {
  8.         if (compareAndSetState(0, 1))
  9.             setExclusiveOwnerThread(Thread.currentThread());
  10.         else
  11.             acquire(1);
  12.     }
  13.     protected final boolean tryAcquire(int acquires) {
  14.         return nonfairTryAcquire(acquires);
  15.     }
  16. }
复制代码
公平锁(ReentrantLock实现)

公平锁是指多个线程按照申请锁的顺序来获取锁,线程直接进入队列中排队,队列中的第一个线程才能获得锁。保证每个线程都能拿到锁,优点是执行效率比非公平锁低,优点是不会出现线程饿死现象。
  1. static final class FairSync extends Sync {
  2.     private static final long serialVersionUID = -3000897897090466540L;
  3.     final void lock() {
  4.         acquire(1);
  5.     }
  6.     /**
  7.      * Fair version of tryAcquire.  Don't grant access unless
  8.      * recursive call or no waiters or is first.
  9.      */
  10.     protected final boolean tryAcquire(int acquires) {
  11.         final Thread current = Thread.currentThread();
  12.         int c = getState();
  13.         if (c == 0) {
  14.             if (!hasQueuedPredecessors() &&
  15.                 compareAndSetState(0, acquires)) {
  16.                 setExclusiveOwnerThread(current);
  17.                 return true;
  18.             }
  19.         }
  20.         else if (current == getExclusiveOwnerThread()) {
  21.             int nextc = c + acquires;
  22.             if (nextc < 0)
  23.                 throw new Error("Maximum lock count exceeded");
  24.             setState(nextc);
  25.             return true;
  26.         }
  27.         return false;
  28.     }
  29. }
复制代码
可重入锁(ReentrantLock实现)

synchronized(隐式)和Lock(显式)都是可重入锁,也叫递归锁。特点,类似于,有了第一把锁,此锁内部锁的代码都可以访问。像开了大门,开剩下的门就不用再用钥匙开门了。
  1. /**
  2. * @author 长名06
  3. * @version 1.0
  4. * 可重入锁案例
  5. */
  6. public class ReentrantLockDemo {
  7.     private synchronized void add(){
  8.         add();
  9.     }
  10.     public static void main(String[] args) {
  11.         //new ReentrantLockDemo().add();//会出现StackOverflowError
  12.         Object o = new Object();
  13.         new Thread(() -> {
  14.             synchronized (o){
  15.                 System.out.println(Thread.currentThread().getName() + "外部");
  16.                 synchronized (o){
  17.                     System.out.println(Thread.currentThread().getName() + "中部");
  18.                     synchronized (o){
  19.                         System.out.println(Thread.currentThread().getName() + "内部");
  20.                     }
  21.                 }
  22.             }
  23.         },"aa").start();
  24.         
  25.         ReentrantLock lock = new ReentrantLock();
  26.         new Thread(() -> {
  27.             try{
  28.                 lock.lock();
  29.                 System.out.println(Thread.currentThread().getName() + "外层操作");
  30.                 try{
  31.                     lock.lock();
  32.                     System.out.println(Thread.currentThread().getName() + "内层操作");
  33.                 }finally {
  34.                     lock.unlock();
  35.                 }
  36.             }finally {
  37.                 lock.unlock();
  38.             }
  39.         }).start();
  40.      //结果
  41.      //Thread-0外层操作
  42.      //Thread-0内层操作
  43.     }
  44. }
复制代码
死锁

基本介绍

死锁,是一种多个线程在执行过程中,因竞争资源时,导致线程互相持有其他线程执行需要的锁,从而引起线程等待的现象。在没有外力的作用下,程序会崩溃。
引起死锁的原因


  • 1.系统资源不足。
  • 2.进程运行顺序不合适。
  • 3.资源分配不当。
  1. /**
  2. * @author 长名06
  3. * @version 1.0
  4. * 死锁代码
  5. */
  6. public class DeadLock {
  7.     static Object a = new Object();
  8.     static Object b = new Object();
  9.     public static void main(String[] args) {
  10.         new Thread(() -> {
  11.             synchronized (a){
  12.                 System.out.println(Thread.currentThread().getName() + "持有锁a,试图后去锁b");
  13.                 try {
  14.                     TimeUnit.SECONDS.sleep(1);
  15.                 } catch (InterruptedException e) {
  16.                     e.printStackTrace();
  17.                 }
  18.                 synchronized (b){
  19.                     System.out.println(Thread.currentThread().getName() + "获取锁b");
  20.                 }
  21.             }
  22.         },"a").start();
  23.         new Thread(() -> {
  24.             synchronized (b){
  25.                 System.out.println(Thread.currentThread().getName() + "持有锁b,试图后去锁a");
  26.                 try {
  27.                     TimeUnit.SECONDS.sleep(1);
  28.                 } catch (InterruptedException e) {
  29.                     e.printStackTrace();
  30.                 }
  31.                 synchronized (a){
  32.                     System.out.println(Thread.currentThread().getName() + "获取锁a");
  33.                 }
  34.             }
  35.         },"b").start();
  36.     }
  37. }
复制代码
验证线程一直等待是否是死锁


  • 1.jps -l 命令类似linux下的ps - ef 可以查询java的线程

    正在执行的死锁代码的进程id
  • 2.jstack工具(JVM 自带的堆栈工具) jstack 线程id 可以查询对应线程的信息
    执行jstack pid指令
    提示语句中会有 Found 1 deadlock
只是为了记录自己的学习历程,且本人水平有限,不对之处,请指正。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

乌市泽哥

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表