• Java的锁


    今天练习了Java的多线程,提到多线程就基本就会用到锁
    Java通过关键字及几个类实现了锁的机制,这里先介绍下Java都有哪些锁:
     
    一、Java实现锁的机制:
    Java运行到包含锁的代码时,获取尝试获取对应的锁,如果锁被其他线程占用着,则该线程默认等待,待这个锁得以释放在去获取,进而执行锁中的代码。
    注:这里说的尝试获取对应的锁是指当多个线程公用一个锁的时候。
     
    二、锁的种类
    Java总共就两个锁:对象锁类锁
     
    区别:
    具体这里分为了对象锁和类锁,是因为锁作用的范围不同,如果多个线程采用的是对象锁,需要要求他们引用同一个对象实例的锁才起作用,一旦一个线程使用的是不同的对象实例,就不受这个锁的干预了,但是类锁不同,类锁对应的是class对象,这个类的所有实例对应一个class对象,所以他们相当于争抢同一个锁。
     
    对象锁:
    说到对象锁,需要在这了统一一个认识:Java里的所有代码都是对对象执行的操作
    其实每个对象都有一个锁,只不过对于没有加锁的代码而言,他们对这个锁视而不见,因为普通代码的执行根本就不依赖锁。
    对象锁的具体表现形式是:
    1. 对方法加的锁
    2. 代码块加的锁
     
    对方法加的锁长这样:
     1 public synchronized void output1() {
     2     for(int i=0;i<10;i++) {
     3         System.out.println(Thread.currentThread().getName());
     4         try {
     5             Thread.sleep(100);
     6         } catch (InterruptedException e) {
     7             e.printStackTrace();
     8         }
     9     }
    10 }
    运行结果如下:
    Synchronized test
    thread1
    thread1
    thread1
    thread1
    thread1
    thread1
    thread1
    thread1
    thread1
    thread1
    thread2
    thread2
    thread2
    thread2
    thread2
    thread2
    thread2
    thread2
    thread2
    thread2
    View Code
     
    对代码块加的锁长这样:
     1 public void output2() {
     2     for(int i=0;i<1;i++) {
     3         System.out.println(Thread.currentThread().getName() + "---read");
     4     }
     5     synchronized(Synchronized_test.syn) {
     6         for(int i=0;i<10;i++) {
     7             System.out.println(Thread.currentThread().getName() + "--- write");
     8             try {
     9                 Thread.sleep(100);
    10             } catch (InterruptedException e) {
    11                 e.printStackTrace();
    12             }
    13         }
    14     }
    15 }
    运行结果如下:
    Synchronized test
    thread1---read
    thread2---read
    thread1---write
    thread1---write
    thread1---write
    thread1---write
    thread1---write
    thread1---write
    thread1---write
    thread1---write
    thread1---write
    thread1---write
    thread2---write
    thread2---write
    thread2---write
    thread2---write
    thread2---write
    thread2---write
    thread2---write
    thread2---write
    thread2---write
    thread2—write
    View Code
     
    实现原理:
    具体的实现方式是,当程序运行到包含锁的代码的时候,不管是方法还是代码块,线程会拿到锁域里的所有对象的锁。如果有方法调用也会递归式的获取。
     
    类锁
    类锁一半针对静态代码块或者静态方法。例子这里就不写了,就是相当于在上面两个例子前面加个static关键字。
    只要是调用这个类的方法,引用类锁的线程争抢的就都是一把锁。
     
     
    三、关于锁的关键字:
    synchronized  
    注:可以指定方法,可以指定代码块
     
    四、实现锁的类
    1. ReentrantLock
    2. Reentrant​ReadWriteLock
     
    这两种锁和synchronized关键字的区别:
    1. 当锁被其他线程获取,当前线程可以不必阻塞住。
    2. 关键字的方式是由系统自动释放锁,而下面必须要手动操作。
     
    ReentranLock的用法
    1. 简单的用法如下,功能同关键字synchronized
     1 @Override
     2 public void run() {
     3     lock.lock();
     4     for(int i=1;i<10;i++) {
     5         System.out.println(Thread.currentThread().getName());
     6         try {
     7             Thread.sleep(100);
     8         } catch (InterruptedException e) {
     9             e.printStackTrace();
    10         }
    11      }
    12     lock.unlock();
    13 }
    运行结果如下:
    lock test
    Thread-0
    Thread-0
    Thread-0
    Thread-0
    Thread-0
    Thread-0
    Thread-0
    Thread-0
    Thread-0
    Thread-1
    Thread-1
    Thread-1
    Thread-1
    Thread-1
    Thread-1
    Thread-1
    Thread-1
    Thread-1
    View Code
     
    1. 实现中断线程
     1 public class Lock_interrupt_test implements Runnable {
     2     private Lock lock = null;
     3     public Lock_interrupt_test() {
     4         lock = new ReentrantLock();
     5     }
     6 
     7     @Override
     8     public void run() {
     9         try {
    10             lock.lockInterruptibly();
    11             for (int i = 0; i < 10; i++) {
    12                 System.out.println(Thread.currentThread().getName());
    13                 Thread.sleep(100);
    14             }
    15         } catch (InterruptedException e1) {
    16             e1.printStackTrace();
    17         } finally {
    18             lock.unlock();
    19         }
    20 }
    21 public static void main(String[] args) {
    22     System.out.println("lock interrupt test");
    23     Lock_interrupt_test lock_interrupt_test = new 
    24 Lock_interrupt_test();
    25     Thread thread1 = new Thread(lock_interrupt_test, "thread1");
    26     Thread thread2 = new Thread(lock_interrupt_test, "thread2");
    27     thread1.start();
    28     thread2.start();
    29     try {
    30         Thread.sleep(400);
    31     } catch (InterruptedException e) {
    32         e.printStackTrace();
    33     }
    34     State state1 = thread1.getState();
    35     Thread thread = state1.toString().equals("TIMED_WAITING")? 
    36 thread1:thread2;
    37     System.out.println("interrupt " + thread.getName());
    38     thread.interrupt();
    39     }
    40 }
    运行结果如下:
    lock interrupt test
    thread1
    thread1
    thread1
    thread1
    interrupt thread1
    java.lang.InterruptedException: sleep interrupted
    at java.base/java.lang.Thread.sleep(Native Method)
    at lock_type.Lock_interrupt_test.run(Lock_interrupt_test.java:21)
    at java.base/java.lang.Thread.run(Thread.java:844)
    thread2
    thread2
    thread2
    thread2
    thread2
    thread2
    thread2
    thread2
    thread2
    thread2
    View Code
     
    1. 实现检测锁状态
     1 @Override
     2 public void run() {
     3     try {
     4         if (lock.tryLock(400,TimeUnit.MILLISECONDS)) {
     5             System.out.println(Thread.currentThread().getName() + " have get the lock");
     6             for (int i = 1; i < 10; i++) {
     7                 System.out.println(Thread.currentThread().getName());
     8                 try {
     9                    Thread.sleep(100);
    10                 } catch (InterruptedException e) {
    11                     e.printStackTrace();
    12                 }
    13             }
    14             System.out.println(Thread.currentThread().getName() + " have 
    15             return the lock");
    16             lock.unlock();
    17         }
    18         else {
    19             for (int i = 1; i < 10; i++) {
    20                 System.out.println(Thread.currentThread().getName() + " locking");
    21                 try {
    22                     Thread.sleep(100);
    23                 } catch (InterruptedException e) {
    24                     e.printStackTrace();
    25                 }
    26             }
    27         }
    28     } catch (InterruptedException e) {
    29         e.printStackTrace();
    30     }
    31 }
    运行结果如下:
    lock try test
    Thread-0 have get the lock
    Thread-0
    Thread-0
    Thread-0
    Thread-0
    Thread-1 locking
    Thread-0
    Thread-1 locking
    Thread-0
    Thread-1 locking
    Thread-0
    Thread-1 locking
    Thread-0
    Thread-1 locking
    Thread-0
    Thread-1 locking
    Thread-0 have return the lock
    Thread-1 locking
    Thread-1 locking
    Thread-1 locking
    View Code
     
    ReentrantReadWriteLock的用法
    实现读写分离锁
     1 @Override
     2 public void run() {
     3     lock.readLock().lock();
     4     for(int i=0;i<10;i++) {
     5         System.out.println(Thread.currentThread().getName() + "---read");
     6         try {
     7             Thread.sleep(100);
     8         } catch (InterruptedException e) {
     9             e.printStackTrace();
    10         }
    11     }
    12     lock.readLock().unlock();
    13     lock.writeLock().lock();
    14     for(int i=0;i<10;i++) {
    15         System.out.println(Thread.currentThread().getName() + "---write");
    16         try {
    17              Thread.sleep(100);
    18         } catch (InterruptedException e) {
    19             e.printStackTrace();
    20         }
    21     }
    22     lock.writeLock().unlock();
    23 }
    运行结果如下:
    lock read write test
    thread2---read
    thread1---read
    thread1---read
    thread2---read
    thread1---read
    thread2---read
    thread2---read
    thread1---read
    thread1---read
    thread2---read
    thread1---read
    thread2---read
    thread1---read
    thread2---read
    thread1---read
    thread2---read
    thread2---read
    thread1---read
    thread2---read
    thread1---read
    thread1---write
    thread1---write
    thread1---write
    thread1---write
    thread1---write
    thread1---write
    thread1---write
    thread1---write
    thread1---write
    thread1---write
    thread2---write
    thread2---write
    thread2---write
    thread2---write
    thread2---write
    thread2---write
    thread2---write
    thread2---write
    thread2---write
    thread2---write
    View Code
  • 相关阅读:
    说说与线程相关的方法
    sleep()和yield()有什么区别?
    同步和异步有何异同,分别在什么情况下使用?
    如何保证多个线程同时启动?
    volatile关键字能否保证线程安全?
    使用对象的wait()方法需要注意什么?
    乐观锁与悲观锁是什么?
    Condition实现等待、唤醒
    LongAdder与AtomicLong有什么区别?
    介绍一下ForkJoinPool的使用
  • 原文地址:https://www.cnblogs.com/xiatianyu/p/9038993.html
Copyright © 2020-2023  润新知